Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / lldb / source / Plugins / Instruction / ARM / EmulateInstructionARM.cpp
blobff5c79aa2455b03936a565ee3d14c434a64cc1b7
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 // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS:
834 is_apple = true;
835 break;
836 default:
837 break;
840 /* On Apple iOS et al, the frame pointer register is always r7.
841 * Typically on other ARM systems, thumb code uses r7; arm code uses r11.
842 * Windows on ARM, which is in thumb mode, uses r11 though.
845 uint32_t fp_regnum = 11;
847 if (is_apple)
848 fp_regnum = 7;
850 if (m_opcode_mode == eModeThumb && !m_arch.GetTriple().isOSWindows())
851 fp_regnum = 7;
853 return fp_regnum;
856 uint32_t EmulateInstructionARM::GetFramePointerDWARFRegisterNumber() const {
857 bool is_apple = false;
858 if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)
859 is_apple = true;
860 switch (m_arch.GetTriple().getOS()) {
861 case llvm::Triple::Darwin:
862 case llvm::Triple::MacOSX:
863 case llvm::Triple::IOS:
864 is_apple = true;
865 break;
866 default:
867 break;
870 /* On Apple iOS et al, the frame pointer register is always r7.
871 * Typically on other ARM systems, thumb code uses r7; arm code uses r11.
872 * Windows on ARM, which is in thumb mode, uses r11 though.
875 uint32_t fp_regnum = dwarf_r11;
877 if (is_apple)
878 fp_regnum = dwarf_r7;
880 if (m_opcode_mode == eModeThumb && !m_arch.GetTriple().isOSWindows())
881 fp_regnum = dwarf_r7;
883 return fp_regnum;
886 // Push Multiple Registers stores multiple registers to the stack, storing to
887 // consecutive memory locations ending just below the address in SP, and
888 // updates
889 // SP to point to the start of the stored data.
890 bool EmulateInstructionARM::EmulatePUSH(const uint32_t opcode,
891 const ARMEncoding encoding) {
892 #if 0
893 // ARM pseudo code...
894 if (ConditionPassed())
896 EncodingSpecificOperations();
897 NullCheckIfThumbEE(13);
898 address = SP - 4*BitCount(registers);
900 for (i = 0 to 14)
902 if (registers<i> == '1')
904 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
905 MemA[address,4] = bits(32) UNKNOWN;
906 else
907 MemA[address,4] = R[i];
908 address = address + 4;
912 if (registers<15> == '1') // Only possible for encoding A1 or A2
913 MemA[address,4] = PCStoreValue();
915 SP = SP - 4*BitCount(registers);
917 #endif
919 bool success = false;
920 if (ConditionPassed(opcode)) {
921 const uint32_t addr_byte_size = GetAddressByteSize();
922 const addr_t sp = ReadCoreReg(SP_REG, &success);
923 if (!success)
924 return false;
925 uint32_t registers = 0;
926 uint32_t Rt; // the source register
927 switch (encoding) {
928 case eEncodingT1:
929 registers = Bits32(opcode, 7, 0);
930 // The M bit represents LR.
931 if (Bit32(opcode, 8))
932 registers |= (1u << 14);
933 // if BitCount(registers) < 1 then UNPREDICTABLE;
934 if (BitCount(registers) < 1)
935 return false;
936 break;
937 case eEncodingT2:
938 // Ignore bits 15 & 13.
939 registers = Bits32(opcode, 15, 0) & ~0xa000;
940 // if BitCount(registers) < 2 then UNPREDICTABLE;
941 if (BitCount(registers) < 2)
942 return false;
943 break;
944 case eEncodingT3:
945 Rt = Bits32(opcode, 15, 12);
946 // if BadReg(t) then UNPREDICTABLE;
947 if (BadReg(Rt))
948 return false;
949 registers = (1u << Rt);
950 break;
951 case eEncodingA1:
952 registers = Bits32(opcode, 15, 0);
953 // Instead of return false, let's handle the following case as well,
954 // which amounts to pushing one reg onto the full descending stacks.
955 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
956 break;
957 case eEncodingA2:
958 Rt = Bits32(opcode, 15, 12);
959 // if t == 13 then UNPREDICTABLE;
960 if (Rt == dwarf_sp)
961 return false;
962 registers = (1u << Rt);
963 break;
964 default:
965 return false;
967 addr_t sp_offset = addr_byte_size * BitCount(registers);
968 addr_t addr = sp - sp_offset;
969 uint32_t i;
971 EmulateInstruction::Context context;
972 context.type = EmulateInstruction::eContextPushRegisterOnStack;
973 std::optional<RegisterInfo> sp_reg =
974 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);
975 for (i = 0; i < 15; ++i) {
976 if (BitIsSet(registers, i)) {
977 std::optional<RegisterInfo> reg_info =
978 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i);
979 context.SetRegisterToRegisterPlusOffset(*reg_info, *sp_reg, addr - sp);
980 uint32_t reg_value = ReadCoreReg(i, &success);
981 if (!success)
982 return false;
983 if (!MemAWrite(context, addr, reg_value, addr_byte_size))
984 return false;
985 addr += addr_byte_size;
989 if (BitIsSet(registers, 15)) {
990 std::optional<RegisterInfo> reg_info =
991 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);
992 context.SetRegisterToRegisterPlusOffset(*reg_info, *sp_reg, addr - sp);
993 const uint32_t pc = ReadCoreReg(PC_REG, &success);
994 if (!success)
995 return false;
996 if (!MemAWrite(context, addr, pc, addr_byte_size))
997 return false;
1000 context.type = EmulateInstruction::eContextAdjustStackPointer;
1001 context.SetImmediateSigned(-sp_offset);
1003 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1004 LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
1005 return false;
1007 return true;
1010 // Pop Multiple Registers loads multiple registers from the stack, loading from
1011 // consecutive memory locations staring at the address in SP, and updates
1012 // SP to point just above the loaded data.
1013 bool EmulateInstructionARM::EmulatePOP(const uint32_t opcode,
1014 const ARMEncoding encoding) {
1015 #if 0
1016 // ARM pseudo code...
1017 if (ConditionPassed())
1019 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
1020 address = SP;
1021 for i = 0 to 14
1022 if registers<i> == '1' then
1023 R[i] = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
1024 if registers<15> == '1' then
1025 if UnalignedAllowed then
1026 LoadWritePC(MemU[address,4]);
1027 else
1028 LoadWritePC(MemA[address,4]);
1029 if registers<13> == '0' then SP = SP + 4*BitCount(registers);
1030 if registers<13> == '1' then SP = bits(32) UNKNOWN;
1032 #endif
1034 bool success = false;
1036 if (ConditionPassed(opcode)) {
1037 const uint32_t addr_byte_size = GetAddressByteSize();
1038 const addr_t sp = ReadCoreReg(SP_REG, &success);
1039 if (!success)
1040 return false;
1041 uint32_t registers = 0;
1042 uint32_t Rt; // the destination register
1043 switch (encoding) {
1044 case eEncodingT1:
1045 registers = Bits32(opcode, 7, 0);
1046 // The P bit represents PC.
1047 if (Bit32(opcode, 8))
1048 registers |= (1u << 15);
1049 // if BitCount(registers) < 1 then UNPREDICTABLE;
1050 if (BitCount(registers) < 1)
1051 return false;
1052 break;
1053 case eEncodingT2:
1054 // Ignore bit 13.
1055 registers = Bits32(opcode, 15, 0) & ~0x2000;
1056 // if BitCount(registers) < 2 || (P == '1' && M == '1') then
1057 // UNPREDICTABLE;
1058 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
1059 return false;
1060 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
1061 // UNPREDICTABLE;
1062 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
1063 return false;
1064 break;
1065 case eEncodingT3:
1066 Rt = Bits32(opcode, 15, 12);
1067 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then
1068 // UNPREDICTABLE;
1069 if (Rt == 13)
1070 return false;
1071 if (Rt == 15 && InITBlock() && !LastInITBlock())
1072 return false;
1073 registers = (1u << Rt);
1074 break;
1075 case eEncodingA1:
1076 registers = Bits32(opcode, 15, 0);
1077 // Instead of return false, let's handle the following case as well,
1078 // which amounts to popping one reg from the full descending stacks.
1079 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
1081 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
1082 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
1083 return false;
1084 break;
1085 case eEncodingA2:
1086 Rt = Bits32(opcode, 15, 12);
1087 // if t == 13 then UNPREDICTABLE;
1088 if (Rt == dwarf_sp)
1089 return false;
1090 registers = (1u << Rt);
1091 break;
1092 default:
1093 return false;
1095 addr_t sp_offset = addr_byte_size * BitCount(registers);
1096 addr_t addr = sp;
1097 uint32_t i, data;
1099 EmulateInstruction::Context context;
1100 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1102 std::optional<RegisterInfo> sp_reg =
1103 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);
1105 for (i = 0; i < 15; ++i) {
1106 if (BitIsSet(registers, i)) {
1107 context.SetAddress(addr);
1108 data = MemARead(context, addr, 4, 0, &success);
1109 if (!success)
1110 return false;
1111 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
1112 data))
1113 return false;
1114 addr += addr_byte_size;
1118 if (BitIsSet(registers, 15)) {
1119 context.SetRegisterPlusOffset(*sp_reg, addr - sp);
1120 data = MemARead(context, addr, 4, 0, &success);
1121 if (!success)
1122 return false;
1123 // In ARMv5T and above, this is an interworking branch.
1124 if (!LoadWritePC(context, data))
1125 return false;
1126 // addr += addr_byte_size;
1129 context.type = EmulateInstruction::eContextAdjustStackPointer;
1130 context.SetImmediateSigned(sp_offset);
1132 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1133 LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1134 return false;
1136 return true;
1139 // Set r7 or ip to point to saved value residing within the stack.
1140 // ADD (SP plus immediate)
1141 bool EmulateInstructionARM::EmulateADDRdSPImm(const uint32_t opcode,
1142 const ARMEncoding encoding) {
1143 #if 0
1144 // ARM pseudo code...
1145 if (ConditionPassed())
1147 EncodingSpecificOperations();
1148 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
1149 if d == 15 then
1150 ALUWritePC(result); // setflags is always FALSE here
1151 else
1152 R[d] = result;
1153 if setflags then
1154 APSR.N = result<31>;
1155 APSR.Z = IsZeroBit(result);
1156 APSR.C = carry;
1157 APSR.V = overflow;
1159 #endif
1161 bool success = false;
1163 if (ConditionPassed(opcode)) {
1164 const addr_t sp = ReadCoreReg(SP_REG, &success);
1165 if (!success)
1166 return false;
1167 uint32_t Rd; // the destination register
1168 uint32_t imm32;
1169 switch (encoding) {
1170 case eEncodingT1:
1171 Rd = 7;
1172 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
1173 break;
1174 case eEncodingA1:
1175 Rd = Bits32(opcode, 15, 12);
1176 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1177 break;
1178 default:
1179 return false;
1181 addr_t sp_offset = imm32;
1182 addr_t addr = sp + sp_offset; // a pointer to the stack area
1184 EmulateInstruction::Context context;
1185 if (Rd == GetFramePointerRegisterNumber())
1186 context.type = eContextSetFramePointer;
1187 else
1188 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1189 std::optional<RegisterInfo> sp_reg =
1190 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);
1191 context.SetRegisterPlusOffset(*sp_reg, sp_offset);
1193 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd,
1194 addr))
1195 return false;
1197 return true;
1200 // Set r7 or ip to the current stack pointer.
1201 // MOV (register)
1202 bool EmulateInstructionARM::EmulateMOVRdSP(const uint32_t opcode,
1203 const ARMEncoding encoding) {
1204 #if 0
1205 // ARM pseudo code...
1206 if (ConditionPassed())
1208 EncodingSpecificOperations();
1209 result = R[m];
1210 if d == 15 then
1211 ALUWritePC(result); // setflags is always FALSE here
1212 else
1213 R[d] = result;
1214 if setflags then
1215 APSR.N = result<31>;
1216 APSR.Z = IsZeroBit(result);
1217 // APSR.C unchanged
1218 // APSR.V unchanged
1220 #endif
1222 bool success = false;
1224 if (ConditionPassed(opcode)) {
1225 const addr_t sp = ReadCoreReg(SP_REG, &success);
1226 if (!success)
1227 return false;
1228 uint32_t Rd; // the destination register
1229 switch (encoding) {
1230 case eEncodingT1:
1231 Rd = 7;
1232 break;
1233 case eEncodingA1:
1234 Rd = 12;
1235 break;
1236 default:
1237 return false;
1240 EmulateInstruction::Context context;
1241 if (Rd == GetFramePointerRegisterNumber())
1242 context.type = EmulateInstruction::eContextSetFramePointer;
1243 else
1244 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1245 std::optional<RegisterInfo> sp_reg =
1246 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);
1247 context.SetRegisterPlusOffset(*sp_reg, 0);
1249 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
1250 return false;
1252 return true;
1255 // Move from high register (r8-r15) to low register (r0-r7).
1256 // MOV (register)
1257 bool EmulateInstructionARM::EmulateMOVLowHigh(const uint32_t opcode,
1258 const ARMEncoding encoding) {
1259 return EmulateMOVRdRm(opcode, encoding);
1262 // Move from register to register.
1263 // MOV (register)
1264 bool EmulateInstructionARM::EmulateMOVRdRm(const uint32_t opcode,
1265 const ARMEncoding encoding) {
1266 #if 0
1267 // ARM pseudo code...
1268 if (ConditionPassed())
1270 EncodingSpecificOperations();
1271 result = R[m];
1272 if d == 15 then
1273 ALUWritePC(result); // setflags is always FALSE here
1274 else
1275 R[d] = result;
1276 if setflags then
1277 APSR.N = result<31>;
1278 APSR.Z = IsZeroBit(result);
1279 // APSR.C unchanged
1280 // APSR.V unchanged
1282 #endif
1284 bool success = false;
1286 if (ConditionPassed(opcode)) {
1287 uint32_t Rm; // the source register
1288 uint32_t Rd; // the destination register
1289 bool setflags;
1290 switch (encoding) {
1291 case eEncodingT1:
1292 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
1293 Rm = Bits32(opcode, 6, 3);
1294 setflags = false;
1295 if (Rd == 15 && InITBlock() && !LastInITBlock())
1296 return false;
1297 break;
1298 case eEncodingT2:
1299 Rd = Bits32(opcode, 2, 0);
1300 Rm = Bits32(opcode, 5, 3);
1301 setflags = true;
1302 if (InITBlock())
1303 return false;
1304 break;
1305 case eEncodingT3:
1306 Rd = Bits32(opcode, 11, 8);
1307 Rm = Bits32(opcode, 3, 0);
1308 setflags = BitIsSet(opcode, 20);
1309 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
1310 if (setflags && (BadReg(Rd) || BadReg(Rm)))
1311 return false;
1312 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then
1313 // UNPREDICTABLE;
1314 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
1315 return false;
1316 break;
1317 case eEncodingA1:
1318 Rd = Bits32(opcode, 15, 12);
1319 Rm = Bits32(opcode, 3, 0);
1320 setflags = BitIsSet(opcode, 20);
1322 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1323 // instructions;
1324 if (Rd == 15 && setflags)
1325 return EmulateSUBSPcLrEtc(opcode, encoding);
1326 break;
1327 default:
1328 return false;
1330 uint32_t result = ReadCoreReg(Rm, &success);
1331 if (!success)
1332 return false;
1334 // The context specifies that Rm is to be moved into Rd.
1335 EmulateInstruction::Context context;
1336 if (Rd == 13)
1337 context.type = EmulateInstruction::eContextAdjustStackPointer;
1338 else if (Rd == GetFramePointerRegisterNumber() && Rm == 13)
1339 context.type = EmulateInstruction::eContextSetFramePointer;
1340 else
1341 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1342 std::optional<RegisterInfo> dwarf_reg =
1343 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);
1344 context.SetRegisterPlusOffset(*dwarf_reg, 0);
1346 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
1347 return false;
1349 return true;
1352 // Move (immediate) writes an immediate value to the destination register. It
1353 // can optionally update the condition flags based on the value.
1354 // MOV (immediate)
1355 bool EmulateInstructionARM::EmulateMOVRdImm(const uint32_t opcode,
1356 const ARMEncoding encoding) {
1357 #if 0
1358 // ARM pseudo code...
1359 if (ConditionPassed())
1361 EncodingSpecificOperations();
1362 result = imm32;
1363 if d == 15 then // Can only occur for ARM encoding
1364 ALUWritePC(result); // setflags is always FALSE here
1365 else
1366 R[d] = result;
1367 if setflags then
1368 APSR.N = result<31>;
1369 APSR.Z = IsZeroBit(result);
1370 APSR.C = carry;
1371 // APSR.V unchanged
1373 #endif
1375 if (ConditionPassed(opcode)) {
1376 uint32_t Rd; // the destination register
1377 uint32_t imm32; // the immediate value to be written to Rd
1378 uint32_t carry =
1379 0; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
1380 // for setflags == false, this value is a don't care initialized to
1381 // 0 to silence the static analyzer
1382 bool setflags;
1383 switch (encoding) {
1384 case eEncodingT1:
1385 Rd = Bits32(opcode, 10, 8);
1386 setflags = !InITBlock();
1387 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
1388 carry = APSR_C;
1390 break;
1392 case eEncodingT2:
1393 Rd = Bits32(opcode, 11, 8);
1394 setflags = BitIsSet(opcode, 20);
1395 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
1396 if (BadReg(Rd))
1397 return false;
1399 break;
1401 case eEncodingT3: {
1402 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8,
1403 // 32);
1404 Rd = Bits32(opcode, 11, 8);
1405 setflags = false;
1406 uint32_t imm4 = Bits32(opcode, 19, 16);
1407 uint32_t imm3 = Bits32(opcode, 14, 12);
1408 uint32_t i = Bit32(opcode, 26);
1409 uint32_t imm8 = Bits32(opcode, 7, 0);
1410 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
1412 // if BadReg(d) then UNPREDICTABLE;
1413 if (BadReg(Rd))
1414 return false;
1415 } break;
1417 case eEncodingA1:
1418 // d = UInt(Rd); setflags = (S == '1'); (imm32, carry) =
1419 // ARMExpandImm_C(imm12, APSR.C);
1420 Rd = Bits32(opcode, 15, 12);
1421 setflags = BitIsSet(opcode, 20);
1422 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
1424 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1425 // instructions;
1426 if ((Rd == 15) && setflags)
1427 return EmulateSUBSPcLrEtc(opcode, encoding);
1429 break;
1431 case eEncodingA2: {
1432 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
1433 Rd = Bits32(opcode, 15, 12);
1434 setflags = false;
1435 uint32_t imm4 = Bits32(opcode, 19, 16);
1436 uint32_t imm12 = Bits32(opcode, 11, 0);
1437 imm32 = (imm4 << 12) | imm12;
1439 // if d == 15 then UNPREDICTABLE;
1440 if (Rd == 15)
1441 return false;
1442 } break;
1444 default:
1445 return false;
1447 uint32_t result = imm32;
1449 // The context specifies that an immediate is to be moved into Rd.
1450 EmulateInstruction::Context context;
1451 context.type = EmulateInstruction::eContextImmediate;
1452 context.SetNoArgs();
1454 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1455 return false;
1457 return true;
1460 // MUL multiplies two register values. The least significant 32 bits of the
1461 // result are written to the destination
1462 // register. These 32 bits do not depend on whether the source register values
1463 // are considered to be signed values or unsigned values.
1465 // Optionally, it can update the condition flags based on the result. In the
1466 // Thumb instruction set, this option is limited to only a few forms of the
1467 // instruction.
1468 bool EmulateInstructionARM::EmulateMUL(const uint32_t opcode,
1469 const ARMEncoding encoding) {
1470 #if 0
1471 if ConditionPassed() then
1472 EncodingSpecificOperations();
1473 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
1474 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
1475 result = operand1 * operand2;
1476 R[d] = result<31:0>;
1477 if setflags then
1478 APSR.N = result<31>;
1479 APSR.Z = IsZeroBit(result);
1480 if ArchVersion() == 4 then
1481 APSR.C = bit UNKNOWN;
1482 // else APSR.C unchanged
1483 // APSR.V always unchanged
1484 #endif
1486 if (ConditionPassed(opcode)) {
1487 uint32_t d;
1488 uint32_t n;
1489 uint32_t m;
1490 bool setflags;
1492 // EncodingSpecificOperations();
1493 switch (encoding) {
1494 case eEncodingT1:
1495 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
1496 d = Bits32(opcode, 2, 0);
1497 n = Bits32(opcode, 5, 3);
1498 m = Bits32(opcode, 2, 0);
1499 setflags = !InITBlock();
1501 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
1502 if ((ArchVersion() < ARMv6) && (d == n))
1503 return false;
1505 break;
1507 case eEncodingT2:
1508 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
1509 d = Bits32(opcode, 11, 8);
1510 n = Bits32(opcode, 19, 16);
1511 m = Bits32(opcode, 3, 0);
1512 setflags = false;
1514 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
1515 if (BadReg(d) || BadReg(n) || BadReg(m))
1516 return false;
1518 break;
1520 case eEncodingA1:
1521 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
1522 d = Bits32(opcode, 19, 16);
1523 n = Bits32(opcode, 3, 0);
1524 m = Bits32(opcode, 11, 8);
1525 setflags = BitIsSet(opcode, 20);
1527 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
1528 if ((d == 15) || (n == 15) || (m == 15))
1529 return false;
1531 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
1532 if ((ArchVersion() < ARMv6) && (d == n))
1533 return false;
1535 break;
1537 default:
1538 return false;
1541 bool success = false;
1543 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final
1544 // results
1545 uint64_t operand1 =
1546 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1547 if (!success)
1548 return false;
1550 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final
1551 // results
1552 uint64_t operand2 =
1553 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
1554 if (!success)
1555 return false;
1557 // result = operand1 * operand2;
1558 uint64_t result = operand1 * operand2;
1560 // R[d] = result<31:0>;
1561 std::optional<RegisterInfo> op1_reg =
1562 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
1563 std::optional<RegisterInfo> op2_reg =
1564 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
1566 EmulateInstruction::Context context;
1567 context.type = eContextArithmetic;
1568 context.SetRegisterRegisterOperands(*op1_reg, *op2_reg);
1570 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
1571 (0x0000ffff & result)))
1572 return false;
1574 // if setflags then
1575 if (setflags) {
1576 // APSR.N = result<31>;
1577 // APSR.Z = IsZeroBit(result);
1578 m_new_inst_cpsr = m_opcode_cpsr;
1579 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, 31));
1580 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
1581 if (m_new_inst_cpsr != m_opcode_cpsr) {
1582 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1583 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
1584 return false;
1587 // if ArchVersion() == 4 then
1588 // APSR.C = bit UNKNOWN;
1591 return true;
1594 // Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to
1595 // the destination register. It can optionally update the condition flags based
1596 // on the value.
1597 bool EmulateInstructionARM::EmulateMVNImm(const uint32_t opcode,
1598 const ARMEncoding encoding) {
1599 #if 0
1600 // ARM pseudo code...
1601 if (ConditionPassed())
1603 EncodingSpecificOperations();
1604 result = NOT(imm32);
1605 if d == 15 then // Can only occur for ARM encoding
1606 ALUWritePC(result); // setflags is always FALSE here
1607 else
1608 R[d] = result;
1609 if setflags then
1610 APSR.N = result<31>;
1611 APSR.Z = IsZeroBit(result);
1612 APSR.C = carry;
1613 // APSR.V unchanged
1615 #endif
1617 if (ConditionPassed(opcode)) {
1618 uint32_t Rd; // the destination register
1619 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
1620 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
1621 bool setflags;
1622 switch (encoding) {
1623 case eEncodingT1:
1624 Rd = Bits32(opcode, 11, 8);
1625 setflags = BitIsSet(opcode, 20);
1626 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
1627 break;
1628 case eEncodingA1:
1629 Rd = Bits32(opcode, 15, 12);
1630 setflags = BitIsSet(opcode, 20);
1631 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
1633 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1634 // instructions;
1635 if (Rd == 15 && setflags)
1636 return EmulateSUBSPcLrEtc(opcode, encoding);
1637 break;
1638 default:
1639 return false;
1641 uint32_t result = ~imm32;
1643 // The context specifies that an immediate is to be moved into Rd.
1644 EmulateInstruction::Context context;
1645 context.type = EmulateInstruction::eContextImmediate;
1646 context.SetNoArgs();
1648 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1649 return false;
1651 return true;
1654 // Bitwise NOT (register) writes the bitwise inverse of a register value to the
1655 // destination register. It can optionally update the condition flags based on
1656 // the result.
1657 bool EmulateInstructionARM::EmulateMVNReg(const uint32_t opcode,
1658 const ARMEncoding encoding) {
1659 #if 0
1660 // ARM pseudo code...
1661 if (ConditionPassed())
1663 EncodingSpecificOperations();
1664 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
1665 result = NOT(shifted);
1666 if d == 15 then // Can only occur for ARM encoding
1667 ALUWritePC(result); // setflags is always FALSE here
1668 else
1669 R[d] = result;
1670 if setflags then
1671 APSR.N = result<31>;
1672 APSR.Z = IsZeroBit(result);
1673 APSR.C = carry;
1674 // APSR.V unchanged
1676 #endif
1678 if (ConditionPassed(opcode)) {
1679 uint32_t Rm; // the source register
1680 uint32_t Rd; // the destination register
1681 ARM_ShifterType shift_t;
1682 uint32_t shift_n; // the shift applied to the value read from Rm
1683 bool setflags;
1684 uint32_t carry; // the carry bit after the shift operation
1685 switch (encoding) {
1686 case eEncodingT1:
1687 Rd = Bits32(opcode, 2, 0);
1688 Rm = Bits32(opcode, 5, 3);
1689 setflags = !InITBlock();
1690 shift_t = SRType_LSL;
1691 shift_n = 0;
1692 if (InITBlock())
1693 return false;
1694 break;
1695 case eEncodingT2:
1696 Rd = Bits32(opcode, 11, 8);
1697 Rm = Bits32(opcode, 3, 0);
1698 setflags = BitIsSet(opcode, 20);
1699 shift_n = DecodeImmShiftThumb(opcode, shift_t);
1700 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
1701 if (BadReg(Rd) || BadReg(Rm))
1702 return false;
1703 break;
1704 case eEncodingA1:
1705 Rd = Bits32(opcode, 15, 12);
1706 Rm = Bits32(opcode, 3, 0);
1707 setflags = BitIsSet(opcode, 20);
1708 shift_n = DecodeImmShiftARM(opcode, shift_t);
1709 break;
1710 default:
1711 return false;
1713 bool success = false;
1714 uint32_t value = ReadCoreReg(Rm, &success);
1715 if (!success)
1716 return false;
1718 uint32_t shifted =
1719 Shift_C(value, shift_t, shift_n, APSR_C, carry, &success);
1720 if (!success)
1721 return false;
1722 uint32_t result = ~shifted;
1724 // The context specifies that an immediate is to be moved into Rd.
1725 EmulateInstruction::Context context;
1726 context.type = EmulateInstruction::eContextImmediate;
1727 context.SetNoArgs();
1729 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1730 return false;
1732 return true;
1735 // PC relative immediate load into register, possibly followed by ADD (SP plus
1736 // register).
1737 // LDR (literal)
1738 bool EmulateInstructionARM::EmulateLDRRtPCRelative(const uint32_t opcode,
1739 const ARMEncoding encoding) {
1740 #if 0
1741 // ARM pseudo code...
1742 if (ConditionPassed())
1744 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1745 base = Align(PC,4);
1746 address = if add then (base + imm32) else (base - imm32);
1747 data = MemU[address,4];
1748 if t == 15 then
1749 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1750 elsif UnalignedSupport() || address<1:0> = '00' then
1751 R[t] = data;
1752 else // Can only apply before ARMv7
1753 if CurrentInstrSet() == InstrSet_ARM then
1754 R[t] = ROR(data, 8*UInt(address<1:0>));
1755 else
1756 R[t] = bits(32) UNKNOWN;
1758 #endif
1760 if (ConditionPassed(opcode)) {
1761 bool success = false;
1762 const uint32_t pc = ReadCoreReg(PC_REG, &success);
1763 if (!success)
1764 return false;
1766 // PC relative immediate load context
1767 EmulateInstruction::Context context;
1768 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1769 std::optional<RegisterInfo> pc_reg =
1770 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);
1771 context.SetRegisterPlusOffset(*pc_reg, 0);
1773 uint32_t Rt; // the destination register
1774 uint32_t imm32; // immediate offset from the PC
1775 bool add; // +imm32 or -imm32?
1776 addr_t base; // the base address
1777 addr_t address; // the PC relative address
1778 uint32_t data; // the literal data value from the PC relative load
1779 switch (encoding) {
1780 case eEncodingT1:
1781 Rt = Bits32(opcode, 10, 8);
1782 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
1783 add = true;
1784 break;
1785 case eEncodingT2:
1786 Rt = Bits32(opcode, 15, 12);
1787 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1788 add = BitIsSet(opcode, 23);
1789 if (Rt == 15 && InITBlock() && !LastInITBlock())
1790 return false;
1791 break;
1792 default:
1793 return false;
1796 base = Align(pc, 4);
1797 if (add)
1798 address = base + imm32;
1799 else
1800 address = base - imm32;
1802 context.SetRegisterPlusOffset(*pc_reg, address - base);
1803 data = MemURead(context, address, 4, 0, &success);
1804 if (!success)
1805 return false;
1807 if (Rt == 15) {
1808 if (Bits32(address, 1, 0) == 0) {
1809 // In ARMv5T and above, this is an interworking branch.
1810 if (!LoadWritePC(context, data))
1811 return false;
1812 } else
1813 return false;
1814 } else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) {
1815 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rt,
1816 data))
1817 return false;
1818 } else // We don't handle ARM for now.
1819 return false;
1821 return true;
1824 // An add operation to adjust the SP.
1825 // ADD (SP plus immediate)
1826 bool EmulateInstructionARM::EmulateADDSPImm(const uint32_t opcode,
1827 const ARMEncoding encoding) {
1828 #if 0
1829 // ARM pseudo code...
1830 if (ConditionPassed())
1832 EncodingSpecificOperations();
1833 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
1834 if d == 15 then // Can only occur for ARM encoding
1835 ALUWritePC(result); // setflags is always FALSE here
1836 else
1837 R[d] = result;
1838 if setflags then
1839 APSR.N = result<31>;
1840 APSR.Z = IsZeroBit(result);
1841 APSR.C = carry;
1842 APSR.V = overflow;
1844 #endif
1846 bool success = false;
1848 if (ConditionPassed(opcode)) {
1849 const addr_t sp = ReadCoreReg(SP_REG, &success);
1850 if (!success)
1851 return false;
1852 uint32_t imm32; // the immediate operand
1853 uint32_t d;
1854 bool setflags;
1855 switch (encoding) {
1856 case eEncodingT1:
1857 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
1858 d = Bits32(opcode, 10, 8);
1859 imm32 = (Bits32(opcode, 7, 0) << 2);
1860 setflags = false;
1861 break;
1863 case eEncodingT2:
1864 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
1865 d = 13;
1866 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1867 setflags = false;
1868 break;
1870 case eEncodingT3:
1871 // d = UInt(Rd); setflags = (S == "1"); imm32 =
1872 // ThumbExpandImm(i:imm3:imm8);
1873 d = Bits32(opcode, 11, 8);
1874 imm32 = ThumbExpandImm(opcode);
1875 setflags = Bit32(opcode, 20);
1877 // if Rd == "1111" && S == "1" then SEE CMN (immediate);
1878 if (d == 15 && setflags == 1)
1879 return false; // CMN (immediate) not yet supported
1881 // if d == 15 && S == "0" then UNPREDICTABLE;
1882 if (d == 15 && setflags == 0)
1883 return false;
1884 break;
1886 case eEncodingT4: {
1887 // if Rn == '1111' then SEE ADR;
1888 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
1889 d = Bits32(opcode, 11, 8);
1890 setflags = false;
1891 uint32_t i = Bit32(opcode, 26);
1892 uint32_t imm3 = Bits32(opcode, 14, 12);
1893 uint32_t imm8 = Bits32(opcode, 7, 0);
1894 imm32 = (i << 11) | (imm3 << 8) | imm8;
1896 // if d == 15 then UNPREDICTABLE;
1897 if (d == 15)
1898 return false;
1899 } break;
1901 default:
1902 return false;
1904 // (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
1905 AddWithCarryResult res = AddWithCarry(sp, imm32, 0);
1907 EmulateInstruction::Context context;
1908 if (d == 13)
1909 context.type = EmulateInstruction::eContextAdjustStackPointer;
1910 else
1911 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1913 std::optional<RegisterInfo> sp_reg =
1914 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);
1915 context.SetRegisterPlusOffset(*sp_reg, res.result - sp);
1917 if (d == 15) {
1918 if (!ALUWritePC(context, res.result))
1919 return false;
1920 } else {
1921 // R[d] = result;
1922 // if setflags then
1923 // APSR.N = result<31>;
1924 // APSR.Z = IsZeroBit(result);
1925 // APSR.C = carry;
1926 // APSR.V = overflow;
1927 if (!WriteCoreRegOptionalFlags(context, res.result, d, setflags,
1928 res.carry_out, res.overflow))
1929 return false;
1932 return true;
1935 // An add operation to adjust the SP.
1936 // ADD (SP plus register)
1937 bool EmulateInstructionARM::EmulateADDSPRm(const uint32_t opcode,
1938 const ARMEncoding encoding) {
1939 #if 0
1940 // ARM pseudo code...
1941 if (ConditionPassed())
1943 EncodingSpecificOperations();
1944 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1945 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
1946 if d == 15 then
1947 ALUWritePC(result); // setflags is always FALSE here
1948 else
1949 R[d] = result;
1950 if setflags then
1951 APSR.N = result<31>;
1952 APSR.Z = IsZeroBit(result);
1953 APSR.C = carry;
1954 APSR.V = overflow;
1956 #endif
1958 bool success = false;
1960 if (ConditionPassed(opcode)) {
1961 const addr_t sp = ReadCoreReg(SP_REG, &success);
1962 if (!success)
1963 return false;
1964 uint32_t Rm; // the second operand
1965 switch (encoding) {
1966 case eEncodingT2:
1967 Rm = Bits32(opcode, 6, 3);
1968 break;
1969 default:
1970 return false;
1972 int32_t reg_value = ReadCoreReg(Rm, &success);
1973 if (!success)
1974 return false;
1976 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1978 EmulateInstruction::Context context;
1979 context.type = eContextArithmetic;
1980 std::optional<RegisterInfo> sp_reg =
1981 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);
1982 std::optional<RegisterInfo> other_reg =
1983 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);
1984 context.SetRegisterRegisterOperands(*sp_reg, *other_reg);
1986 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1987 LLDB_REGNUM_GENERIC_SP, addr))
1988 return false;
1990 return true;
1993 // Branch with Link and Exchange Instruction Sets (immediate) calls a
1994 // subroutine at a PC-relative address, and changes instruction set from ARM to
1995 // Thumb, or from Thumb to ARM.
1996 // BLX (immediate)
1997 bool EmulateInstructionARM::EmulateBLXImmediate(const uint32_t opcode,
1998 const ARMEncoding encoding) {
1999 #if 0
2000 // ARM pseudo code...
2001 if (ConditionPassed())
2003 EncodingSpecificOperations();
2004 if CurrentInstrSet() == InstrSet_ARM then
2005 LR = PC - 4;
2006 else
2007 LR = PC<31:1> : '1';
2008 if targetInstrSet == InstrSet_ARM then
2009 targetAddress = Align(PC,4) + imm32;
2010 else
2011 targetAddress = PC + imm32;
2012 SelectInstrSet(targetInstrSet);
2013 BranchWritePC(targetAddress);
2015 #endif
2017 bool success = true;
2019 if (ConditionPassed(opcode)) {
2020 EmulateInstruction::Context context;
2021 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2022 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2023 if (!success)
2024 return false;
2025 addr_t lr; // next instruction address
2026 addr_t target; // target address
2027 int32_t imm32; // PC-relative offset
2028 switch (encoding) {
2029 case eEncodingT1: {
2030 lr = pc | 1u; // return address
2031 uint32_t S = Bit32(opcode, 26);
2032 uint32_t imm10 = Bits32(opcode, 25, 16);
2033 uint32_t J1 = Bit32(opcode, 13);
2034 uint32_t J2 = Bit32(opcode, 11);
2035 uint32_t imm11 = Bits32(opcode, 10, 0);
2036 uint32_t I1 = !(J1 ^ S);
2037 uint32_t I2 = !(J2 ^ S);
2038 uint32_t imm25 =
2039 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
2040 imm32 = llvm::SignExtend32<25>(imm25);
2041 target = pc + imm32;
2042 SelectInstrSet(eModeThumb);
2043 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2044 if (InITBlock() && !LastInITBlock())
2045 return false;
2046 break;
2048 case eEncodingT2: {
2049 lr = pc | 1u; // return address
2050 uint32_t S = Bit32(opcode, 26);
2051 uint32_t imm10H = Bits32(opcode, 25, 16);
2052 uint32_t J1 = Bit32(opcode, 13);
2053 uint32_t J2 = Bit32(opcode, 11);
2054 uint32_t imm10L = Bits32(opcode, 10, 1);
2055 uint32_t I1 = !(J1 ^ S);
2056 uint32_t I2 = !(J2 ^ S);
2057 uint32_t imm25 =
2058 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
2059 imm32 = llvm::SignExtend32<25>(imm25);
2060 target = Align(pc, 4) + imm32;
2061 SelectInstrSet(eModeARM);
2062 context.SetISAAndImmediateSigned(eModeARM, 4 + imm32);
2063 if (InITBlock() && !LastInITBlock())
2064 return false;
2065 break;
2067 case eEncodingA1:
2068 lr = pc - 4; // return address
2069 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
2070 target = Align(pc, 4) + imm32;
2071 SelectInstrSet(eModeARM);
2072 context.SetISAAndImmediateSigned(eModeARM, 8 + imm32);
2073 break;
2074 case eEncodingA2:
2075 lr = pc - 4; // return address
2076 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 |
2077 Bits32(opcode, 24, 24) << 1);
2078 target = pc + imm32;
2079 SelectInstrSet(eModeThumb);
2080 context.SetISAAndImmediateSigned(eModeThumb, 8 + imm32);
2081 break;
2082 default:
2083 return false;
2085 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2086 LLDB_REGNUM_GENERIC_RA, lr))
2087 return false;
2088 if (!BranchWritePC(context, target))
2089 return false;
2090 if (m_opcode_cpsr != m_new_inst_cpsr)
2091 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2092 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2093 return false;
2095 return true;
2098 // Branch with Link and Exchange (register) calls a subroutine at an address
2099 // and instruction set specified by a register.
2100 // BLX (register)
2101 bool EmulateInstructionARM::EmulateBLXRm(const uint32_t opcode,
2102 const ARMEncoding encoding) {
2103 #if 0
2104 // ARM pseudo code...
2105 if (ConditionPassed())
2107 EncodingSpecificOperations();
2108 target = R[m];
2109 if CurrentInstrSet() == InstrSet_ARM then
2110 next_instr_addr = PC - 4;
2111 LR = next_instr_addr;
2112 else
2113 next_instr_addr = PC - 2;
2114 LR = next_instr_addr<31:1> : '1';
2115 BXWritePC(target);
2117 #endif
2119 bool success = false;
2121 if (ConditionPassed(opcode)) {
2122 EmulateInstruction::Context context;
2123 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
2124 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2125 addr_t lr; // next instruction address
2126 if (!success)
2127 return false;
2128 uint32_t Rm; // the register with the target address
2129 switch (encoding) {
2130 case eEncodingT1:
2131 lr = (pc - 2) | 1u; // return address
2132 Rm = Bits32(opcode, 6, 3);
2133 // if m == 15 then UNPREDICTABLE;
2134 if (Rm == 15)
2135 return false;
2136 if (InITBlock() && !LastInITBlock())
2137 return false;
2138 break;
2139 case eEncodingA1:
2140 lr = pc - 4; // return address
2141 Rm = Bits32(opcode, 3, 0);
2142 // if m == 15 then UNPREDICTABLE;
2143 if (Rm == 15)
2144 return false;
2145 break;
2146 default:
2147 return false;
2149 addr_t target = ReadCoreReg(Rm, &success);
2150 if (!success)
2151 return false;
2152 std::optional<RegisterInfo> dwarf_reg =
2153 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);
2154 context.SetRegister(*dwarf_reg);
2155 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2156 LLDB_REGNUM_GENERIC_RA, lr))
2157 return false;
2158 if (!BXWritePC(context, target))
2159 return false;
2161 return true;
2164 // Branch and Exchange causes a branch to an address and instruction set
2165 // specified by a register.
2166 bool EmulateInstructionARM::EmulateBXRm(const uint32_t opcode,
2167 const ARMEncoding encoding) {
2168 #if 0
2169 // ARM pseudo code...
2170 if (ConditionPassed())
2172 EncodingSpecificOperations();
2173 BXWritePC(R[m]);
2175 #endif
2177 if (ConditionPassed(opcode)) {
2178 EmulateInstruction::Context context;
2179 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
2180 uint32_t Rm; // the register with the target address
2181 switch (encoding) {
2182 case eEncodingT1:
2183 Rm = Bits32(opcode, 6, 3);
2184 if (InITBlock() && !LastInITBlock())
2185 return false;
2186 break;
2187 case eEncodingA1:
2188 Rm = Bits32(opcode, 3, 0);
2189 break;
2190 default:
2191 return false;
2193 bool success = false;
2194 addr_t target = ReadCoreReg(Rm, &success);
2195 if (!success)
2196 return false;
2198 std::optional<RegisterInfo> dwarf_reg =
2199 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);
2200 context.SetRegister(*dwarf_reg);
2201 if (!BXWritePC(context, target))
2202 return false;
2204 return true;
2207 // Branch and Exchange Jazelle attempts to change to Jazelle state. If the
2208 // attempt fails, it branches to an address and instruction set specified by a
2209 // register as though it were a BX instruction.
2211 // TODO: Emulate Jazelle architecture?
2212 // We currently assume that switching to Jazelle state fails, thus
2213 // treating BXJ as a BX operation.
2214 bool EmulateInstructionARM::EmulateBXJRm(const uint32_t opcode,
2215 const ARMEncoding encoding) {
2216 #if 0
2217 // ARM pseudo code...
2218 if (ConditionPassed())
2220 EncodingSpecificOperations();
2221 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
2222 BXWritePC(R[m]);
2223 else
2224 if JazelleAcceptsExecution() then
2225 SwitchToJazelleExecution();
2226 else
2227 SUBARCHITECTURE_DEFINED handler call;
2229 #endif
2231 if (ConditionPassed(opcode)) {
2232 EmulateInstruction::Context context;
2233 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
2234 uint32_t Rm; // the register with the target address
2235 switch (encoding) {
2236 case eEncodingT1:
2237 Rm = Bits32(opcode, 19, 16);
2238 if (BadReg(Rm))
2239 return false;
2240 if (InITBlock() && !LastInITBlock())
2241 return false;
2242 break;
2243 case eEncodingA1:
2244 Rm = Bits32(opcode, 3, 0);
2245 if (Rm == 15)
2246 return false;
2247 break;
2248 default:
2249 return false;
2251 bool success = false;
2252 addr_t target = ReadCoreReg(Rm, &success);
2253 if (!success)
2254 return false;
2256 std::optional<RegisterInfo> dwarf_reg =
2257 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);
2258 context.SetRegister(*dwarf_reg);
2259 if (!BXWritePC(context, target))
2260 return false;
2262 return true;
2265 // Set r7 to point to some ip offset.
2266 // SUB (immediate)
2267 bool EmulateInstructionARM::EmulateSUBR7IPImm(const uint32_t opcode,
2268 const ARMEncoding encoding) {
2269 #if 0
2270 // ARM pseudo code...
2271 if (ConditionPassed())
2273 EncodingSpecificOperations();
2274 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
2275 if d == 15 then // Can only occur for ARM encoding
2276 ALUWritePC(result); // setflags is always FALSE here
2277 else
2278 R[d] = result;
2279 if setflags then
2280 APSR.N = result<31>;
2281 APSR.Z = IsZeroBit(result);
2282 APSR.C = carry;
2283 APSR.V = overflow;
2285 #endif
2287 if (ConditionPassed(opcode)) {
2288 bool success = false;
2289 const addr_t ip = ReadCoreReg(12, &success);
2290 if (!success)
2291 return false;
2292 uint32_t imm32;
2293 switch (encoding) {
2294 case eEncodingA1:
2295 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2296 break;
2297 default:
2298 return false;
2300 addr_t ip_offset = imm32;
2301 addr_t addr = ip - ip_offset; // the adjusted ip value
2303 EmulateInstruction::Context context;
2304 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2305 std::optional<RegisterInfo> dwarf_reg =
2306 GetRegisterInfo(eRegisterKindDWARF, dwarf_r12);
2307 context.SetRegisterPlusOffset(*dwarf_reg, -ip_offset);
2309 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r7, addr))
2310 return false;
2312 return true;
2315 // Set ip to point to some stack offset.
2316 // SUB (SP minus immediate)
2317 bool EmulateInstructionARM::EmulateSUBIPSPImm(const uint32_t opcode,
2318 const ARMEncoding encoding) {
2319 #if 0
2320 // ARM pseudo code...
2321 if (ConditionPassed())
2323 EncodingSpecificOperations();
2324 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
2325 if d == 15 then // Can only occur for ARM encoding
2326 ALUWritePC(result); // setflags is always FALSE here
2327 else
2328 R[d] = result;
2329 if setflags then
2330 APSR.N = result<31>;
2331 APSR.Z = IsZeroBit(result);
2332 APSR.C = carry;
2333 APSR.V = overflow;
2335 #endif
2337 if (ConditionPassed(opcode)) {
2338 bool success = false;
2339 const addr_t sp = ReadCoreReg(SP_REG, &success);
2340 if (!success)
2341 return false;
2342 uint32_t imm32;
2343 switch (encoding) {
2344 case eEncodingA1:
2345 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2346 break;
2347 default:
2348 return false;
2350 addr_t sp_offset = imm32;
2351 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
2353 EmulateInstruction::Context context;
2354 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2355 std::optional<RegisterInfo> dwarf_reg =
2356 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
2357 context.SetRegisterPlusOffset(*dwarf_reg, -sp_offset);
2359 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r12, addr))
2360 return false;
2362 return true;
2365 // This instruction subtracts an immediate value from the SP value, and writes
2366 // the result to the destination register.
2368 // If Rd == 13 => A sub operation to adjust the SP -- allocate space for local
2369 // storage.
2370 bool EmulateInstructionARM::EmulateSUBSPImm(const uint32_t opcode,
2371 const ARMEncoding encoding) {
2372 #if 0
2373 // ARM pseudo code...
2374 if (ConditionPassed())
2376 EncodingSpecificOperations();
2377 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
2378 if d == 15 then // Can only occur for ARM encoding
2379 ALUWritePC(result); // setflags is always FALSE here
2380 else
2381 R[d] = result;
2382 if setflags then
2383 APSR.N = result<31>;
2384 APSR.Z = IsZeroBit(result);
2385 APSR.C = carry;
2386 APSR.V = overflow;
2388 #endif
2390 bool success = false;
2391 if (ConditionPassed(opcode)) {
2392 const addr_t sp = ReadCoreReg(SP_REG, &success);
2393 if (!success)
2394 return false;
2396 uint32_t Rd;
2397 bool setflags;
2398 uint32_t imm32;
2399 switch (encoding) {
2400 case eEncodingT1:
2401 Rd = 13;
2402 setflags = false;
2403 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
2404 break;
2405 case eEncodingT2:
2406 Rd = Bits32(opcode, 11, 8);
2407 setflags = BitIsSet(opcode, 20);
2408 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2409 if (Rd == 15 && setflags)
2410 return EmulateCMPImm(opcode, eEncodingT2);
2411 if (Rd == 15 && !setflags)
2412 return false;
2413 break;
2414 case eEncodingT3:
2415 Rd = Bits32(opcode, 11, 8);
2416 setflags = false;
2417 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
2418 if (Rd == 15)
2419 return false;
2420 break;
2421 case eEncodingA1:
2422 Rd = Bits32(opcode, 15, 12);
2423 setflags = BitIsSet(opcode, 20);
2424 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2426 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
2427 // instructions;
2428 if (Rd == 15 && setflags)
2429 return EmulateSUBSPcLrEtc(opcode, encoding);
2430 break;
2431 default:
2432 return false;
2434 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
2436 EmulateInstruction::Context context;
2437 if (Rd == 13) {
2438 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting
2439 // to negate it, or the wrong
2440 // value gets passed down to context.SetImmediateSigned.
2441 context.type = EmulateInstruction::eContextAdjustStackPointer;
2442 context.SetImmediateSigned(-imm64); // the stack pointer offset
2443 } else {
2444 context.type = EmulateInstruction::eContextImmediate;
2445 context.SetNoArgs();
2448 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
2449 res.carry_out, res.overflow))
2450 return false;
2452 return true;
2455 // A store operation to the stack that also updates the SP.
2456 bool EmulateInstructionARM::EmulateSTRRtSP(const uint32_t opcode,
2457 const ARMEncoding encoding) {
2458 #if 0
2459 // ARM pseudo code...
2460 if (ConditionPassed())
2462 EncodingSpecificOperations();
2463 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
2464 address = if index then offset_addr else R[n];
2465 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
2466 if wback then R[n] = offset_addr;
2468 #endif
2470 bool success = false;
2471 if (ConditionPassed(opcode)) {
2472 const uint32_t addr_byte_size = GetAddressByteSize();
2473 const addr_t sp = ReadCoreReg(SP_REG, &success);
2474 if (!success)
2475 return false;
2476 uint32_t Rt; // the source register
2477 uint32_t imm12;
2478 uint32_t
2479 Rn; // This function assumes Rn is the SP, but we should verify that.
2481 bool index;
2482 bool add;
2483 bool wback;
2484 switch (encoding) {
2485 case eEncodingA1:
2486 Rt = Bits32(opcode, 15, 12);
2487 imm12 = Bits32(opcode, 11, 0);
2488 Rn = Bits32(opcode, 19, 16);
2490 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
2491 return false;
2493 index = BitIsSet(opcode, 24);
2494 add = BitIsSet(opcode, 23);
2495 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
2497 if (wback && ((Rn == 15) || (Rn == Rt)))
2498 return false;
2499 break;
2500 default:
2501 return false;
2503 addr_t offset_addr;
2504 if (add)
2505 offset_addr = sp + imm12;
2506 else
2507 offset_addr = sp - imm12;
2509 addr_t addr;
2510 if (index)
2511 addr = offset_addr;
2512 else
2513 addr = sp;
2515 EmulateInstruction::Context context;
2516 context.type = EmulateInstruction::eContextPushRegisterOnStack;
2517 std::optional<RegisterInfo> sp_reg =
2518 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);
2519 std::optional<RegisterInfo> dwarf_reg =
2520 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rt);
2522 context.SetRegisterToRegisterPlusOffset(*dwarf_reg, *sp_reg, addr - sp);
2523 if (Rt != 15) {
2524 uint32_t reg_value = ReadCoreReg(Rt, &success);
2525 if (!success)
2526 return false;
2527 if (!MemUWrite(context, addr, reg_value, addr_byte_size))
2528 return false;
2529 } else {
2530 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2531 if (!success)
2532 return false;
2533 if (!MemUWrite(context, addr, pc, addr_byte_size))
2534 return false;
2537 if (wback) {
2538 context.type = EmulateInstruction::eContextAdjustStackPointer;
2539 context.SetImmediateSigned(addr - sp);
2540 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2541 LLDB_REGNUM_GENERIC_SP, offset_addr))
2542 return false;
2545 return true;
2548 // Vector Push stores multiple extension registers to the stack. It also
2549 // updates SP to point to the start of the stored data.
2550 bool EmulateInstructionARM::EmulateVPUSH(const uint32_t opcode,
2551 const ARMEncoding encoding) {
2552 #if 0
2553 // ARM pseudo code...
2554 if (ConditionPassed())
2556 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2557 address = SP - imm32;
2558 SP = SP - imm32;
2559 if single_regs then
2560 for r = 0 to regs-1
2561 MemA[address,4] = S[d+r]; address = address+4;
2562 else
2563 for r = 0 to regs-1
2564 // Store as two word-aligned words in the correct order for
2565 // current endianness.
2566 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
2567 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
2568 address = address+8;
2570 #endif
2572 bool success = false;
2573 if (ConditionPassed(opcode)) {
2574 const uint32_t addr_byte_size = GetAddressByteSize();
2575 const addr_t sp = ReadCoreReg(SP_REG, &success);
2576 if (!success)
2577 return false;
2578 bool single_regs;
2579 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2580 uint32_t imm32; // stack offset
2581 uint32_t regs; // number of registers
2582 switch (encoding) {
2583 case eEncodingT1:
2584 case eEncodingA1:
2585 single_regs = false;
2586 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
2587 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2588 // If UInt(imm8) is odd, see "FSTMX".
2589 regs = Bits32(opcode, 7, 0) / 2;
2590 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2591 if (regs == 0 || regs > 16 || (d + regs) > 32)
2592 return false;
2593 break;
2594 case eEncodingT2:
2595 case eEncodingA2:
2596 single_regs = true;
2597 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
2598 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2599 regs = Bits32(opcode, 7, 0);
2600 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2601 if (regs == 0 || regs > 16 || (d + regs) > 32)
2602 return false;
2603 break;
2604 default:
2605 return false;
2607 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2608 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2609 addr_t sp_offset = imm32;
2610 addr_t addr = sp - sp_offset;
2611 uint32_t i;
2613 EmulateInstruction::Context context;
2614 context.type = EmulateInstruction::eContextPushRegisterOnStack;
2616 std::optional<RegisterInfo> sp_reg =
2617 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);
2618 for (i = 0; i < regs; ++i) {
2619 std::optional<RegisterInfo> dwarf_reg =
2620 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i);
2621 context.SetRegisterToRegisterPlusOffset(*dwarf_reg, *sp_reg, addr - sp);
2622 // uint64_t to accommodate 64-bit registers.
2623 uint64_t reg_value = ReadRegisterUnsigned(*dwarf_reg, 0, &success);
2624 if (!success)
2625 return false;
2626 if (!MemAWrite(context, addr, reg_value, reg_byte_size))
2627 return false;
2628 addr += reg_byte_size;
2631 context.type = EmulateInstruction::eContextAdjustStackPointer;
2632 context.SetImmediateSigned(-sp_offset);
2634 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2635 LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
2636 return false;
2638 return true;
2641 // Vector Pop loads multiple extension registers from the stack. It also
2642 // updates SP to point just above the loaded data.
2643 bool EmulateInstructionARM::EmulateVPOP(const uint32_t opcode,
2644 const ARMEncoding encoding) {
2645 #if 0
2646 // ARM pseudo code...
2647 if (ConditionPassed())
2649 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2650 address = SP;
2651 SP = SP + imm32;
2652 if single_regs then
2653 for r = 0 to regs-1
2654 S[d+r] = MemA[address,4]; address = address+4;
2655 else
2656 for r = 0 to regs-1
2657 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
2658 // Combine the word-aligned words in the correct order for
2659 // current endianness.
2660 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
2662 #endif
2664 bool success = false;
2665 if (ConditionPassed(opcode)) {
2666 const uint32_t addr_byte_size = GetAddressByteSize();
2667 const addr_t sp = ReadCoreReg(SP_REG, &success);
2668 if (!success)
2669 return false;
2670 bool single_regs;
2671 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2672 uint32_t imm32; // stack offset
2673 uint32_t regs; // number of registers
2674 switch (encoding) {
2675 case eEncodingT1:
2676 case eEncodingA1:
2677 single_regs = false;
2678 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
2679 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2680 // If UInt(imm8) is odd, see "FLDMX".
2681 regs = Bits32(opcode, 7, 0) / 2;
2682 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2683 if (regs == 0 || regs > 16 || (d + regs) > 32)
2684 return false;
2685 break;
2686 case eEncodingT2:
2687 case eEncodingA2:
2688 single_regs = true;
2689 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
2690 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2691 regs = Bits32(opcode, 7, 0);
2692 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2693 if (regs == 0 || regs > 16 || (d + regs) > 32)
2694 return false;
2695 break;
2696 default:
2697 return false;
2699 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2700 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2701 addr_t sp_offset = imm32;
2702 addr_t addr = sp;
2703 uint32_t i;
2704 uint64_t data; // uint64_t to accommodate 64-bit registers.
2706 EmulateInstruction::Context context;
2707 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2709 for (i = 0; i < regs; ++i) {
2710 std::optional<RegisterInfo> dwarf_reg =
2711 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i);
2712 context.SetAddress(addr);
2713 data = MemARead(context, addr, reg_byte_size, 0, &success);
2714 if (!success)
2715 return false;
2716 if (!WriteRegisterUnsigned(context, *dwarf_reg, data))
2717 return false;
2718 addr += reg_byte_size;
2721 context.type = EmulateInstruction::eContextAdjustStackPointer;
2722 context.SetImmediateSigned(sp_offset);
2724 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2725 LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2726 return false;
2728 return true;
2731 // SVC (previously SWI)
2732 bool EmulateInstructionARM::EmulateSVC(const uint32_t opcode,
2733 const ARMEncoding encoding) {
2734 #if 0
2735 // ARM pseudo code...
2736 if (ConditionPassed())
2738 EncodingSpecificOperations();
2739 CallSupervisor();
2741 #endif
2743 bool success = false;
2745 if (ConditionPassed(opcode)) {
2746 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2747 addr_t lr; // next instruction address
2748 if (!success)
2749 return false;
2750 uint32_t imm32; // the immediate constant
2751 uint32_t mode; // ARM or Thumb mode
2752 switch (encoding) {
2753 case eEncodingT1:
2754 lr = (pc + 2) | 1u; // return address
2755 imm32 = Bits32(opcode, 7, 0);
2756 mode = eModeThumb;
2757 break;
2758 case eEncodingA1:
2759 lr = pc + 4; // return address
2760 imm32 = Bits32(opcode, 23, 0);
2761 mode = eModeARM;
2762 break;
2763 default:
2764 return false;
2767 EmulateInstruction::Context context;
2768 context.type = EmulateInstruction::eContextSupervisorCall;
2769 context.SetISAAndImmediate(mode, imm32);
2770 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2771 LLDB_REGNUM_GENERIC_RA, lr))
2772 return false;
2774 return true;
2777 // If Then makes up to four following instructions (the IT block) conditional.
2778 bool EmulateInstructionARM::EmulateIT(const uint32_t opcode,
2779 const ARMEncoding encoding) {
2780 #if 0
2781 // ARM pseudo code...
2782 EncodingSpecificOperations();
2783 ITSTATE.IT<7:0> = firstcond:mask;
2784 #endif
2786 m_it_session.InitIT(Bits32(opcode, 7, 0));
2787 return true;
2790 bool EmulateInstructionARM::EmulateNop(const uint32_t opcode,
2791 const ARMEncoding encoding) {
2792 // NOP, nothing to do...
2793 return true;
2796 // Branch causes a branch to a target address.
2797 bool EmulateInstructionARM::EmulateB(const uint32_t opcode,
2798 const ARMEncoding encoding) {
2799 #if 0
2800 // ARM pseudo code...
2801 if (ConditionPassed())
2803 EncodingSpecificOperations();
2804 BranchWritePC(PC + imm32);
2806 #endif
2808 bool success = false;
2810 if (ConditionPassed(opcode)) {
2811 EmulateInstruction::Context context;
2812 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2813 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2814 if (!success)
2815 return false;
2816 addr_t target; // target address
2817 int32_t imm32; // PC-relative offset
2818 switch (encoding) {
2819 case eEncodingT1:
2820 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2821 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
2822 target = pc + imm32;
2823 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2824 break;
2825 case eEncodingT2:
2826 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0) << 1);
2827 target = pc + imm32;
2828 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2829 break;
2830 case eEncodingT3:
2831 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2833 if (Bits32(opcode, 25, 23) == 7)
2834 return false; // See Branches and miscellaneous control on page
2835 // A6-235.
2837 uint32_t S = Bit32(opcode, 26);
2838 uint32_t imm6 = Bits32(opcode, 21, 16);
2839 uint32_t J1 = Bit32(opcode, 13);
2840 uint32_t J2 = Bit32(opcode, 11);
2841 uint32_t imm11 = Bits32(opcode, 10, 0);
2842 uint32_t imm21 =
2843 (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
2844 imm32 = llvm::SignExtend32<21>(imm21);
2845 target = pc + imm32;
2846 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2847 break;
2849 case eEncodingT4: {
2850 uint32_t S = Bit32(opcode, 26);
2851 uint32_t imm10 = Bits32(opcode, 25, 16);
2852 uint32_t J1 = Bit32(opcode, 13);
2853 uint32_t J2 = Bit32(opcode, 11);
2854 uint32_t imm11 = Bits32(opcode, 10, 0);
2855 uint32_t I1 = !(J1 ^ S);
2856 uint32_t I2 = !(J2 ^ S);
2857 uint32_t imm25 =
2858 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
2859 imm32 = llvm::SignExtend32<25>(imm25);
2860 target = pc + imm32;
2861 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2862 break;
2864 case eEncodingA1:
2865 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
2866 target = pc + imm32;
2867 context.SetISAAndImmediateSigned(eModeARM, 8 + imm32);
2868 break;
2869 default:
2870 return false;
2872 if (!BranchWritePC(context, target))
2873 return false;
2875 return true;
2878 // Compare and Branch on Nonzero and Compare and Branch on Zero compare the
2879 // value in a register with zero and conditionally branch forward a constant
2880 // value. They do not affect the condition flags. CBNZ, CBZ
2881 bool EmulateInstructionARM::EmulateCB(const uint32_t opcode,
2882 const ARMEncoding encoding) {
2883 #if 0
2884 // ARM pseudo code...
2885 EncodingSpecificOperations();
2886 if nonzero ^ IsZero(R[n]) then
2887 BranchWritePC(PC + imm32);
2888 #endif
2890 bool success = false;
2892 // Read the register value from the operand register Rn.
2893 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
2894 if (!success)
2895 return false;
2897 EmulateInstruction::Context context;
2898 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2899 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2900 if (!success)
2901 return false;
2903 addr_t target; // target address
2904 uint32_t imm32; // PC-relative offset to branch forward
2905 bool nonzero;
2906 switch (encoding) {
2907 case eEncodingT1:
2908 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
2909 nonzero = BitIsSet(opcode, 11);
2910 target = pc + imm32;
2911 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2912 break;
2913 default:
2914 return false;
2916 if (m_ignore_conditions || (nonzero ^ (reg_val == 0)))
2917 if (!BranchWritePC(context, target))
2918 return false;
2920 return true;
2923 // Table Branch Byte causes a PC-relative forward branch using a table of
2924 // single byte offsets.
2925 // A base register provides a pointer to the table, and a second register
2926 // supplies an index into the table.
2927 // The branch length is twice the value of the byte returned from the table.
2929 // Table Branch Halfword causes a PC-relative forward branch using a table of
2930 // single halfword offsets.
2931 // A base register provides a pointer to the table, and a second register
2932 // supplies an index into the table.
2933 // The branch length is twice the value of the halfword returned from the
2934 // table. TBB, TBH
2935 bool EmulateInstructionARM::EmulateTB(const uint32_t opcode,
2936 const ARMEncoding encoding) {
2937 #if 0
2938 // ARM pseudo code...
2939 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2940 if is_tbh then
2941 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2942 else
2943 halfwords = UInt(MemU[R[n]+R[m], 1]);
2944 BranchWritePC(PC + 2*halfwords);
2945 #endif
2947 bool success = false;
2949 if (ConditionPassed(opcode)) {
2950 uint32_t Rn; // the base register which contains the address of the table of
2951 // branch lengths
2952 uint32_t Rm; // the index register which contains an integer pointing to a
2953 // byte/halfword in the table
2954 bool is_tbh; // true if table branch halfword
2955 switch (encoding) {
2956 case eEncodingT1:
2957 Rn = Bits32(opcode, 19, 16);
2958 Rm = Bits32(opcode, 3, 0);
2959 is_tbh = BitIsSet(opcode, 4);
2960 if (Rn == 13 || BadReg(Rm))
2961 return false;
2962 if (InITBlock() && !LastInITBlock())
2963 return false;
2964 break;
2965 default:
2966 return false;
2969 // Read the address of the table from the operand register Rn. The PC can
2970 // be used, in which case the table immediately follows this instruction.
2971 uint32_t base = ReadCoreReg(Rn, &success);
2972 if (!success)
2973 return false;
2975 // the table index
2976 uint32_t index = ReadCoreReg(Rm, &success);
2977 if (!success)
2978 return false;
2980 // the offsetted table address
2981 addr_t addr = base + (is_tbh ? index * 2 : index);
2983 // PC-relative offset to branch forward
2984 EmulateInstruction::Context context;
2985 context.type = EmulateInstruction::eContextTableBranchReadMemory;
2986 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
2987 if (!success)
2988 return false;
2990 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2991 if (!success)
2992 return false;
2994 // target address
2995 addr_t target = pc + offset;
2996 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2997 context.SetISAAndImmediateSigned(eModeThumb, 4 + offset);
2999 if (!BranchWritePC(context, target))
3000 return false;
3003 return true;
3006 // This instruction adds an immediate value to a register value, and writes the
3007 // result to the destination register. It can optionally update the condition
3008 // flags based on the result.
3009 bool EmulateInstructionARM::EmulateADDImmThumb(const uint32_t opcode,
3010 const ARMEncoding encoding) {
3011 #if 0
3012 if ConditionPassed() then
3013 EncodingSpecificOperations();
3014 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3015 R[d] = result;
3016 if setflags then
3017 APSR.N = result<31>;
3018 APSR.Z = IsZeroBit(result);
3019 APSR.C = carry;
3020 APSR.V = overflow;
3021 #endif
3023 bool success = false;
3025 if (ConditionPassed(opcode)) {
3026 uint32_t d;
3027 uint32_t n;
3028 bool setflags;
3029 uint32_t imm32;
3030 uint32_t carry_out;
3032 // EncodingSpecificOperations();
3033 switch (encoding) {
3034 case eEncodingT1:
3035 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 =
3036 // ZeroExtend(imm3, 32);
3037 d = Bits32(opcode, 2, 0);
3038 n = Bits32(opcode, 5, 3);
3039 setflags = !InITBlock();
3040 imm32 = Bits32(opcode, 8, 6);
3042 break;
3044 case eEncodingT2:
3045 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 =
3046 // ZeroExtend(imm8, 32);
3047 d = Bits32(opcode, 10, 8);
3048 n = Bits32(opcode, 10, 8);
3049 setflags = !InITBlock();
3050 imm32 = Bits32(opcode, 7, 0);
3052 break;
3054 case eEncodingT3:
3055 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
3056 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 =
3057 // ThumbExpandImm(i:imm3:imm8);
3058 d = Bits32(opcode, 11, 8);
3059 n = Bits32(opcode, 19, 16);
3060 setflags = BitIsSet(opcode, 20);
3061 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry_out);
3063 // if Rn == '1101' then SEE ADD (SP plus immediate);
3064 if (n == 13)
3065 return EmulateADDSPImm(opcode, eEncodingT3);
3067 // if BadReg(d) || n == 15 then UNPREDICTABLE;
3068 if (BadReg(d) || (n == 15))
3069 return false;
3071 break;
3073 case eEncodingT4: {
3074 // if Rn == '1111' then SEE ADR;
3075 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 =
3076 // ZeroExtend(i:imm3:imm8, 32);
3077 d = Bits32(opcode, 11, 8);
3078 n = Bits32(opcode, 19, 16);
3079 setflags = false;
3080 uint32_t i = Bit32(opcode, 26);
3081 uint32_t imm3 = Bits32(opcode, 14, 12);
3082 uint32_t imm8 = Bits32(opcode, 7, 0);
3083 imm32 = (i << 11) | (imm3 << 8) | imm8;
3085 // if Rn == '1101' then SEE ADD (SP plus immediate);
3086 if (n == 13)
3087 return EmulateADDSPImm(opcode, eEncodingT4);
3089 // if BadReg(d) then UNPREDICTABLE;
3090 if (BadReg(d))
3091 return false;
3093 break;
3096 default:
3097 return false;
3100 uint64_t Rn =
3101 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3102 if (!success)
3103 return false;
3105 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3106 AddWithCarryResult res = AddWithCarry(Rn, imm32, 0);
3108 std::optional<RegisterInfo> reg_n =
3109 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
3110 EmulateInstruction::Context context;
3111 context.type = eContextArithmetic;
3112 context.SetRegisterPlusOffset(*reg_n, imm32);
3114 // R[d] = result;
3115 // if setflags then
3116 // APSR.N = result<31>;
3117 // APSR.Z = IsZeroBit(result);
3118 // APSR.C = carry;
3119 // APSR.V = overflow;
3120 if (!WriteCoreRegOptionalFlags(context, res.result, d, setflags,
3121 res.carry_out, res.overflow))
3122 return false;
3124 return true;
3127 // This instruction adds an immediate value to a register value, and writes the
3128 // result to the destination register. It can optionally update the condition
3129 // flags based on the result.
3130 bool EmulateInstructionARM::EmulateADDImmARM(const uint32_t opcode,
3131 const ARMEncoding encoding) {
3132 #if 0
3133 // ARM pseudo code...
3134 if ConditionPassed() then
3135 EncodingSpecificOperations();
3136 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3137 if d == 15 then
3138 ALUWritePC(result); // setflags is always FALSE here
3139 else
3140 R[d] = result;
3141 if setflags then
3142 APSR.N = result<31>;
3143 APSR.Z = IsZeroBit(result);
3144 APSR.C = carry;
3145 APSR.V = overflow;
3146 #endif
3148 bool success = false;
3150 if (ConditionPassed(opcode)) {
3151 uint32_t Rd, Rn;
3152 uint32_t
3153 imm32; // the immediate value to be added to the value obtained from Rn
3154 bool setflags;
3155 switch (encoding) {
3156 case eEncodingA1:
3157 Rd = Bits32(opcode, 15, 12);
3158 Rn = Bits32(opcode, 19, 16);
3159 setflags = BitIsSet(opcode, 20);
3160 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3161 break;
3162 default:
3163 return false;
3166 // Read the first operand.
3167 uint32_t val1 = ReadCoreReg(Rn, &success);
3168 if (!success)
3169 return false;
3171 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
3173 EmulateInstruction::Context context;
3174 if (Rd == 13)
3175 context.type = EmulateInstruction::eContextAdjustStackPointer;
3176 else if (Rd == GetFramePointerRegisterNumber())
3177 context.type = EmulateInstruction::eContextSetFramePointer;
3178 else
3179 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3181 std::optional<RegisterInfo> dwarf_reg =
3182 GetRegisterInfo(eRegisterKindDWARF, Rn);
3183 context.SetRegisterPlusOffset(*dwarf_reg, imm32);
3185 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
3186 res.carry_out, res.overflow))
3187 return false;
3189 return true;
3192 // This instruction adds a register value and an optionally-shifted register
3193 // value, and writes the result to the destination register. It can optionally
3194 // update the condition flags based on the result.
3195 bool EmulateInstructionARM::EmulateADDReg(const uint32_t opcode,
3196 const ARMEncoding encoding) {
3197 #if 0
3198 // ARM pseudo code...
3199 if ConditionPassed() then
3200 EncodingSpecificOperations();
3201 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
3202 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
3203 if d == 15 then
3204 ALUWritePC(result); // setflags is always FALSE here
3205 else
3206 R[d] = result;
3207 if setflags then
3208 APSR.N = result<31>;
3209 APSR.Z = IsZeroBit(result);
3210 APSR.C = carry;
3211 APSR.V = overflow;
3212 #endif
3214 bool success = false;
3216 if (ConditionPassed(opcode)) {
3217 uint32_t Rd, Rn, Rm;
3218 ARM_ShifterType shift_t;
3219 uint32_t shift_n; // the shift applied to the value read from Rm
3220 bool setflags;
3221 switch (encoding) {
3222 case eEncodingT1:
3223 Rd = Bits32(opcode, 2, 0);
3224 Rn = Bits32(opcode, 5, 3);
3225 Rm = Bits32(opcode, 8, 6);
3226 setflags = !InITBlock();
3227 shift_t = SRType_LSL;
3228 shift_n = 0;
3229 break;
3230 case eEncodingT2:
3231 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
3232 Rm = Bits32(opcode, 6, 3);
3233 setflags = false;
3234 shift_t = SRType_LSL;
3235 shift_n = 0;
3236 if (Rn == 15 && Rm == 15)
3237 return false;
3238 if (Rd == 15 && InITBlock() && !LastInITBlock())
3239 return false;
3240 break;
3241 case eEncodingA1:
3242 Rd = Bits32(opcode, 15, 12);
3243 Rn = Bits32(opcode, 19, 16);
3244 Rm = Bits32(opcode, 3, 0);
3245 setflags = BitIsSet(opcode, 20);
3246 shift_n = DecodeImmShiftARM(opcode, shift_t);
3247 break;
3248 default:
3249 return false;
3252 // Read the first operand.
3253 uint32_t val1 = ReadCoreReg(Rn, &success);
3254 if (!success)
3255 return false;
3257 // Read the second operand.
3258 uint32_t val2 = ReadCoreReg(Rm, &success);
3259 if (!success)
3260 return false;
3262 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
3263 if (!success)
3264 return false;
3265 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
3267 EmulateInstruction::Context context;
3268 context.type = eContextArithmetic;
3269 std::optional<RegisterInfo> op1_reg =
3270 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn);
3271 std::optional<RegisterInfo> op2_reg =
3272 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);
3273 context.SetRegisterRegisterOperands(*op1_reg, *op2_reg);
3275 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
3276 res.carry_out, res.overflow))
3277 return false;
3279 return true;
3282 // Compare Negative (immediate) adds a register value and an immediate value.
3283 // It updates the condition flags based on the result, and discards the result.
3284 bool EmulateInstructionARM::EmulateCMNImm(const uint32_t opcode,
3285 const ARMEncoding encoding) {
3286 #if 0
3287 // ARM pseudo code...
3288 if ConditionPassed() then
3289 EncodingSpecificOperations();
3290 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3291 APSR.N = result<31>;
3292 APSR.Z = IsZeroBit(result);
3293 APSR.C = carry;
3294 APSR.V = overflow;
3295 #endif
3297 bool success = false;
3299 uint32_t Rn; // the first operand
3300 uint32_t imm32; // the immediate value to be compared with
3301 switch (encoding) {
3302 case eEncodingT1:
3303 Rn = Bits32(opcode, 19, 16);
3304 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
3305 if (Rn == 15)
3306 return false;
3307 break;
3308 case eEncodingA1:
3309 Rn = Bits32(opcode, 19, 16);
3310 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3311 break;
3312 default:
3313 return false;
3315 // Read the register value from the operand register Rn.
3316 uint32_t reg_val = ReadCoreReg(Rn, &success);
3317 if (!success)
3318 return false;
3320 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
3322 EmulateInstruction::Context context;
3323 context.type = EmulateInstruction::eContextImmediate;
3324 context.SetNoArgs();
3325 return WriteFlags(context, res.result, res.carry_out, res.overflow);
3328 // Compare Negative (register) adds a register value and an optionally-shifted
3329 // register value. It updates the condition flags based on the result, and
3330 // discards the result.
3331 bool EmulateInstructionARM::EmulateCMNReg(const uint32_t opcode,
3332 const ARMEncoding encoding) {
3333 #if 0
3334 // ARM pseudo code...
3335 if ConditionPassed() then
3336 EncodingSpecificOperations();
3337 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
3338 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
3339 APSR.N = result<31>;
3340 APSR.Z = IsZeroBit(result);
3341 APSR.C = carry;
3342 APSR.V = overflow;
3343 #endif
3345 bool success = false;
3347 uint32_t Rn; // the first operand
3348 uint32_t Rm; // the second operand
3349 ARM_ShifterType shift_t;
3350 uint32_t shift_n; // the shift applied to the value read from Rm
3351 switch (encoding) {
3352 case eEncodingT1:
3353 Rn = Bits32(opcode, 2, 0);
3354 Rm = Bits32(opcode, 5, 3);
3355 shift_t = SRType_LSL;
3356 shift_n = 0;
3357 break;
3358 case eEncodingT2:
3359 Rn = Bits32(opcode, 19, 16);
3360 Rm = Bits32(opcode, 3, 0);
3361 shift_n = DecodeImmShiftThumb(opcode, shift_t);
3362 // if n == 15 || BadReg(m) then UNPREDICTABLE;
3363 if (Rn == 15 || BadReg(Rm))
3364 return false;
3365 break;
3366 case eEncodingA1:
3367 Rn = Bits32(opcode, 19, 16);
3368 Rm = Bits32(opcode, 3, 0);
3369 shift_n = DecodeImmShiftARM(opcode, shift_t);
3370 break;
3371 default:
3372 return false;
3374 // Read the register value from register Rn.
3375 uint32_t val1 = ReadCoreReg(Rn, &success);
3376 if (!success)
3377 return false;
3379 // Read the register value from register Rm.
3380 uint32_t val2 = ReadCoreReg(Rm, &success);
3381 if (!success)
3382 return false;
3384 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
3385 if (!success)
3386 return false;
3387 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
3389 EmulateInstruction::Context context;
3390 context.type = EmulateInstruction::eContextImmediate;
3391 context.SetNoArgs();
3392 return WriteFlags(context, res.result, res.carry_out, res.overflow);
3395 // Compare (immediate) subtracts an immediate value from a register value. It
3396 // updates the condition flags based on the result, and discards the result.
3397 bool EmulateInstructionARM::EmulateCMPImm(const uint32_t opcode,
3398 const ARMEncoding encoding) {
3399 #if 0
3400 // ARM pseudo code...
3401 if ConditionPassed() then
3402 EncodingSpecificOperations();
3403 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
3404 APSR.N = result<31>;
3405 APSR.Z = IsZeroBit(result);
3406 APSR.C = carry;
3407 APSR.V = overflow;
3408 #endif
3410 bool success = false;
3412 uint32_t Rn; // the first operand
3413 uint32_t imm32; // the immediate value to be compared with
3414 switch (encoding) {
3415 case eEncodingT1:
3416 Rn = Bits32(opcode, 10, 8);
3417 imm32 = Bits32(opcode, 7, 0);
3418 break;
3419 case eEncodingT2:
3420 Rn = Bits32(opcode, 19, 16);
3421 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
3422 if (Rn == 15)
3423 return false;
3424 break;
3425 case eEncodingA1:
3426 Rn = Bits32(opcode, 19, 16);
3427 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3428 break;
3429 default:
3430 return false;
3432 // Read the register value from the operand register Rn.
3433 uint32_t reg_val = ReadCoreReg(Rn, &success);
3434 if (!success)
3435 return false;
3437 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
3439 EmulateInstruction::Context context;
3440 context.type = EmulateInstruction::eContextImmediate;
3441 context.SetNoArgs();
3442 return WriteFlags(context, res.result, res.carry_out, res.overflow);
3445 // Compare (register) subtracts an optionally-shifted register value from a
3446 // register value. It updates the condition flags based on the result, and
3447 // discards the result.
3448 bool EmulateInstructionARM::EmulateCMPReg(const uint32_t opcode,
3449 const ARMEncoding encoding) {
3450 #if 0
3451 // ARM pseudo code...
3452 if ConditionPassed() then
3453 EncodingSpecificOperations();
3454 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
3455 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
3456 APSR.N = result<31>;
3457 APSR.Z = IsZeroBit(result);
3458 APSR.C = carry;
3459 APSR.V = overflow;
3460 #endif
3462 bool success = false;
3464 uint32_t Rn; // the first operand
3465 uint32_t Rm; // the second operand
3466 ARM_ShifterType shift_t;
3467 uint32_t shift_n; // the shift applied to the value read from Rm
3468 switch (encoding) {
3469 case eEncodingT1:
3470 Rn = Bits32(opcode, 2, 0);
3471 Rm = Bits32(opcode, 5, 3);
3472 shift_t = SRType_LSL;
3473 shift_n = 0;
3474 break;
3475 case eEncodingT2:
3476 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
3477 Rm = Bits32(opcode, 6, 3);
3478 shift_t = SRType_LSL;
3479 shift_n = 0;
3480 if (Rn < 8 && Rm < 8)
3481 return false;
3482 if (Rn == 15 || Rm == 15)
3483 return false;
3484 break;
3485 case eEncodingT3:
3486 Rn = Bits32(opcode, 19, 16);
3487 Rm = Bits32(opcode, 3, 0);
3488 shift_n = DecodeImmShiftThumb(opcode, shift_t);
3489 if (Rn == 15 || BadReg(Rm))
3490 return false;
3491 break;
3492 case eEncodingA1:
3493 Rn = Bits32(opcode, 19, 16);
3494 Rm = Bits32(opcode, 3, 0);
3495 shift_n = DecodeImmShiftARM(opcode, shift_t);
3496 break;
3497 default:
3498 return false;
3500 // Read the register value from register Rn.
3501 uint32_t val1 = ReadCoreReg(Rn, &success);
3502 if (!success)
3503 return false;
3505 // Read the register value from register Rm.
3506 uint32_t val2 = ReadCoreReg(Rm, &success);
3507 if (!success)
3508 return false;
3510 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
3511 if (!success)
3512 return false;
3513 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
3515 EmulateInstruction::Context context;
3516 context.type = EmulateInstruction::eContextImmediate;
3517 context.SetNoArgs();
3518 return WriteFlags(context, res.result, res.carry_out, res.overflow);
3521 // Arithmetic Shift Right (immediate) shifts a register value right by an
3522 // immediate number of bits, shifting in copies of its sign bit, and writes the
3523 // result to the destination register. It can optionally update the condition
3524 // flags based on the result.
3525 bool EmulateInstructionARM::EmulateASRImm(const uint32_t opcode,
3526 const ARMEncoding encoding) {
3527 #if 0
3528 // ARM pseudo code...
3529 if ConditionPassed() then
3530 EncodingSpecificOperations();
3531 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
3532 if d == 15 then // Can only occur for ARM encoding
3533 ALUWritePC(result); // setflags is always FALSE here
3534 else
3535 R[d] = result;
3536 if setflags then
3537 APSR.N = result<31>;
3538 APSR.Z = IsZeroBit(result);
3539 APSR.C = carry;
3540 // APSR.V unchanged
3541 #endif
3543 return EmulateShiftImm(opcode, encoding, SRType_ASR);
3546 // Arithmetic Shift Right (register) shifts a register value right by a
3547 // variable number of bits, shifting in copies of its sign bit, and writes the
3548 // result to the destination register. The variable number of bits is read from
3549 // the bottom byte of a register. It can optionally update the condition flags
3550 // based on the result.
3551 bool EmulateInstructionARM::EmulateASRReg(const uint32_t opcode,
3552 const ARMEncoding encoding) {
3553 #if 0
3554 // ARM pseudo code...
3555 if ConditionPassed() then
3556 EncodingSpecificOperations();
3557 shift_n = UInt(R[m]<7:0>);
3558 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
3559 R[d] = result;
3560 if setflags then
3561 APSR.N = result<31>;
3562 APSR.Z = IsZeroBit(result);
3563 APSR.C = carry;
3564 // APSR.V unchanged
3565 #endif
3567 return EmulateShiftReg(opcode, encoding, SRType_ASR);
3570 // Logical Shift Left (immediate) shifts a register value left by an immediate
3571 // number of bits, shifting in zeros, and writes the result to the destination
3572 // register. It can optionally update the condition flags based on the result.
3573 bool EmulateInstructionARM::EmulateLSLImm(const uint32_t opcode,
3574 const ARMEncoding encoding) {
3575 #if 0
3576 // ARM pseudo code...
3577 if ConditionPassed() then
3578 EncodingSpecificOperations();
3579 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
3580 if d == 15 then // Can only occur for ARM encoding
3581 ALUWritePC(result); // setflags is always FALSE here
3582 else
3583 R[d] = result;
3584 if setflags then
3585 APSR.N = result<31>;
3586 APSR.Z = IsZeroBit(result);
3587 APSR.C = carry;
3588 // APSR.V unchanged
3589 #endif
3591 return EmulateShiftImm(opcode, encoding, SRType_LSL);
3594 // Logical Shift Left (register) shifts a register value left by a variable
3595 // number of bits, shifting in zeros, and writes the result to the destination
3596 // register. The variable number of bits is read from the bottom byte of a
3597 // register. It can optionally update the condition flags based on the result.
3598 bool EmulateInstructionARM::EmulateLSLReg(const uint32_t opcode,
3599 const ARMEncoding encoding) {
3600 #if 0
3601 // ARM pseudo code...
3602 if ConditionPassed() then
3603 EncodingSpecificOperations();
3604 shift_n = UInt(R[m]<7:0>);
3605 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
3606 R[d] = result;
3607 if setflags then
3608 APSR.N = result<31>;
3609 APSR.Z = IsZeroBit(result);
3610 APSR.C = carry;
3611 // APSR.V unchanged
3612 #endif
3614 return EmulateShiftReg(opcode, encoding, SRType_LSL);
3617 // Logical Shift Right (immediate) shifts a register value right by an
3618 // immediate number of bits, shifting in zeros, and writes the result to the
3619 // destination register. It can optionally update the condition flags based on
3620 // the result.
3621 bool EmulateInstructionARM::EmulateLSRImm(const uint32_t opcode,
3622 const ARMEncoding encoding) {
3623 #if 0
3624 // ARM pseudo code...
3625 if ConditionPassed() then
3626 EncodingSpecificOperations();
3627 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3628 if d == 15 then // Can only occur for ARM encoding
3629 ALUWritePC(result); // setflags is always FALSE here
3630 else
3631 R[d] = result;
3632 if setflags then
3633 APSR.N = result<31>;
3634 APSR.Z = IsZeroBit(result);
3635 APSR.C = carry;
3636 // APSR.V unchanged
3637 #endif
3639 return EmulateShiftImm(opcode, encoding, SRType_LSR);
3642 // Logical Shift Right (register) shifts a register value right by a variable
3643 // number of bits, shifting in zeros, and writes the result to the destination
3644 // register. The variable number of bits is read from the bottom byte of a
3645 // register. It can optionally update the condition flags based on the result.
3646 bool EmulateInstructionARM::EmulateLSRReg(const uint32_t opcode,
3647 const ARMEncoding encoding) {
3648 #if 0
3649 // ARM pseudo code...
3650 if ConditionPassed() then
3651 EncodingSpecificOperations();
3652 shift_n = UInt(R[m]<7:0>);
3653 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3654 R[d] = result;
3655 if setflags then
3656 APSR.N = result<31>;
3657 APSR.Z = IsZeroBit(result);
3658 APSR.C = carry;
3659 // APSR.V unchanged
3660 #endif
3662 return EmulateShiftReg(opcode, encoding, SRType_LSR);
3665 // Rotate Right (immediate) provides the value of the contents of a register
3666 // rotated by a constant value. The bits that are rotated off the right end are
3667 // inserted into the vacated bit positions on the left. It can optionally
3668 // update the condition flags based on the result.
3669 bool EmulateInstructionARM::EmulateRORImm(const uint32_t opcode,
3670 const ARMEncoding encoding) {
3671 #if 0
3672 // ARM pseudo code...
3673 if ConditionPassed() then
3674 EncodingSpecificOperations();
3675 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3676 if d == 15 then // Can only occur for ARM encoding
3677 ALUWritePC(result); // setflags is always FALSE here
3678 else
3679 R[d] = result;
3680 if setflags then
3681 APSR.N = result<31>;
3682 APSR.Z = IsZeroBit(result);
3683 APSR.C = carry;
3684 // APSR.V unchanged
3685 #endif
3687 return EmulateShiftImm(opcode, encoding, SRType_ROR);
3690 // Rotate Right (register) provides the value of the contents of a register
3691 // rotated by a variable number of bits. The bits that are rotated off the
3692 // right end are inserted into the vacated bit positions on the left. The
3693 // variable number of bits is read from the bottom byte of a register. It can
3694 // optionally update the condition flags based on the result.
3695 bool EmulateInstructionARM::EmulateRORReg(const uint32_t opcode,
3696 const ARMEncoding encoding) {
3697 #if 0
3698 // ARM pseudo code...
3699 if ConditionPassed() then
3700 EncodingSpecificOperations();
3701 shift_n = UInt(R[m]<7:0>);
3702 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3703 R[d] = result;
3704 if setflags then
3705 APSR.N = result<31>;
3706 APSR.Z = IsZeroBit(result);
3707 APSR.C = carry;
3708 // APSR.V unchanged
3709 #endif
3711 return EmulateShiftReg(opcode, encoding, SRType_ROR);
3714 // Rotate Right with Extend provides the value of the contents of a register
3715 // shifted right by one place, with the carry flag shifted into bit [31].
3717 // RRX can optionally update the condition flags based on the result.
3718 // In that case, bit [0] is shifted into the carry flag.
3719 bool EmulateInstructionARM::EmulateRRX(const uint32_t opcode,
3720 const ARMEncoding encoding) {
3721 #if 0
3722 // ARM pseudo code...
3723 if ConditionPassed() then
3724 EncodingSpecificOperations();
3725 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3726 if d == 15 then // Can only occur for ARM encoding
3727 ALUWritePC(result); // setflags is always FALSE here
3728 else
3729 R[d] = result;
3730 if setflags then
3731 APSR.N = result<31>;
3732 APSR.Z = IsZeroBit(result);
3733 APSR.C = carry;
3734 // APSR.V unchanged
3735 #endif
3737 return EmulateShiftImm(opcode, encoding, SRType_RRX);
3740 bool EmulateInstructionARM::EmulateShiftImm(const uint32_t opcode,
3741 const ARMEncoding encoding,
3742 ARM_ShifterType shift_type) {
3743 // assert(shift_type == SRType_ASR
3744 // || shift_type == SRType_LSL
3745 // || shift_type == SRType_LSR
3746 // || shift_type == SRType_ROR
3747 // || shift_type == SRType_RRX);
3749 bool success = false;
3751 if (ConditionPassed(opcode)) {
3752 uint32_t Rd; // the destination register
3753 uint32_t Rm; // the first operand register
3754 uint32_t imm5; // encoding for the shift amount
3755 uint32_t carry; // the carry bit after the shift operation
3756 bool setflags;
3758 // Special case handling!
3759 // A8.6.139 ROR (immediate) -- Encoding T1
3760 ARMEncoding use_encoding = encoding;
3761 if (shift_type == SRType_ROR && use_encoding == eEncodingT1) {
3762 // Morph the T1 encoding from the ARM Architecture Manual into T2
3763 // encoding to have the same decoding of bit fields as the other Thumb2
3764 // shift operations.
3765 use_encoding = eEncodingT2;
3768 switch (use_encoding) {
3769 case eEncodingT1:
3770 Rd = Bits32(opcode, 2, 0);
3771 Rm = Bits32(opcode, 5, 3);
3772 setflags = !InITBlock();
3773 imm5 = Bits32(opcode, 10, 6);
3774 break;
3775 case eEncodingT2:
3776 // A8.6.141 RRX
3777 // There's no imm form of RRX instructions.
3778 if (shift_type == SRType_RRX)
3779 return false;
3781 Rd = Bits32(opcode, 11, 8);
3782 Rm = Bits32(opcode, 3, 0);
3783 setflags = BitIsSet(opcode, 20);
3784 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3785 if (BadReg(Rd) || BadReg(Rm))
3786 return false;
3787 break;
3788 case eEncodingA1:
3789 Rd = Bits32(opcode, 15, 12);
3790 Rm = Bits32(opcode, 3, 0);
3791 setflags = BitIsSet(opcode, 20);
3792 imm5 = Bits32(opcode, 11, 7);
3793 break;
3794 default:
3795 return false;
3798 // A8.6.139 ROR (immediate)
3799 if (shift_type == SRType_ROR && imm5 == 0)
3800 shift_type = SRType_RRX;
3802 // Get the first operand.
3803 uint32_t value = ReadCoreReg(Rm, &success);
3804 if (!success)
3805 return false;
3807 // Decode the shift amount if not RRX.
3808 uint32_t amt =
3809 (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
3811 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3812 if (!success)
3813 return false;
3815 // The context specifies that an immediate is to be moved into Rd.
3816 EmulateInstruction::Context context;
3817 context.type = EmulateInstruction::eContextImmediate;
3818 context.SetNoArgs();
3820 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3821 return false;
3823 return true;
3826 bool EmulateInstructionARM::EmulateShiftReg(const uint32_t opcode,
3827 const ARMEncoding encoding,
3828 ARM_ShifterType shift_type) {
3829 // assert(shift_type == SRType_ASR
3830 // || shift_type == SRType_LSL
3831 // || shift_type == SRType_LSR
3832 // || shift_type == SRType_ROR);
3834 bool success = false;
3836 if (ConditionPassed(opcode)) {
3837 uint32_t Rd; // the destination register
3838 uint32_t Rn; // the first operand register
3839 uint32_t
3840 Rm; // the register whose bottom byte contains the amount to shift by
3841 uint32_t carry; // the carry bit after the shift operation
3842 bool setflags;
3843 switch (encoding) {
3844 case eEncodingT1:
3845 Rd = Bits32(opcode, 2, 0);
3846 Rn = Rd;
3847 Rm = Bits32(opcode, 5, 3);
3848 setflags = !InITBlock();
3849 break;
3850 case eEncodingT2:
3851 Rd = Bits32(opcode, 11, 8);
3852 Rn = Bits32(opcode, 19, 16);
3853 Rm = Bits32(opcode, 3, 0);
3854 setflags = BitIsSet(opcode, 20);
3855 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3856 return false;
3857 break;
3858 case eEncodingA1:
3859 Rd = Bits32(opcode, 15, 12);
3860 Rn = Bits32(opcode, 3, 0);
3861 Rm = Bits32(opcode, 11, 8);
3862 setflags = BitIsSet(opcode, 20);
3863 if (Rd == 15 || Rn == 15 || Rm == 15)
3864 return false;
3865 break;
3866 default:
3867 return false;
3870 // Get the first operand.
3871 uint32_t value = ReadCoreReg(Rn, &success);
3872 if (!success)
3873 return false;
3874 // Get the Rm register content.
3875 uint32_t val = ReadCoreReg(Rm, &success);
3876 if (!success)
3877 return false;
3879 // Get the shift amount.
3880 uint32_t amt = Bits32(val, 7, 0);
3882 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3883 if (!success)
3884 return false;
3886 // The context specifies that an immediate is to be moved into Rd.
3887 EmulateInstruction::Context context;
3888 context.type = EmulateInstruction::eContextImmediate;
3889 context.SetNoArgs();
3891 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3892 return false;
3894 return true;
3897 // LDM loads multiple registers from consecutive memory locations, using an
3898 // address from a base register. Optionally the address just above the highest
3899 // of those locations can be written back to the base register.
3900 bool EmulateInstructionARM::EmulateLDM(const uint32_t opcode,
3901 const ARMEncoding encoding) {
3902 #if 0
3903 // ARM pseudo code...
3904 if ConditionPassed()
3905 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3906 address = R[n];
3908 for i = 0 to 14
3909 if registers<i> == '1' then
3910 R[i] = MemA[address, 4]; address = address + 4;
3911 if registers<15> == '1' then
3912 LoadWritePC (MemA[address, 4]);
3914 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3915 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3917 #endif
3919 bool success = false;
3920 if (ConditionPassed(opcode)) {
3921 uint32_t n;
3922 uint32_t registers = 0;
3923 bool wback;
3924 const uint32_t addr_byte_size = GetAddressByteSize();
3925 switch (encoding) {
3926 case eEncodingT1:
3927 // n = UInt(Rn); registers = '00000000':register_list; wback =
3928 // (registers<n> == '0');
3929 n = Bits32(opcode, 10, 8);
3930 registers = Bits32(opcode, 7, 0);
3931 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
3932 wback = BitIsClear(registers, n);
3933 // if BitCount(registers) < 1 then UNPREDICTABLE;
3934 if (BitCount(registers) < 1)
3935 return false;
3936 break;
3937 case eEncodingT2:
3938 // if W == '1' && Rn == '1101' then SEE POP;
3939 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
3940 n = Bits32(opcode, 19, 16);
3941 registers = Bits32(opcode, 15, 0);
3942 registers = registers & 0xdfff; // Make sure bit 13 is zero.
3943 wback = BitIsSet(opcode, 21);
3945 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then
3946 // UNPREDICTABLE;
3947 if ((n == 15) || (BitCount(registers) < 2) ||
3948 (BitIsSet(opcode, 14) && BitIsSet(opcode, 15)))
3949 return false;
3951 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
3952 // UNPREDICTABLE;
3953 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
3954 return false;
3956 // if wback && registers<n> == '1' then UNPREDICTABLE;
3957 if (wback && BitIsSet(registers, n))
3958 return false;
3959 break;
3961 case eEncodingA1:
3962 n = Bits32(opcode, 19, 16);
3963 registers = Bits32(opcode, 15, 0);
3964 wback = BitIsSet(opcode, 21);
3965 if ((n == 15) || (BitCount(registers) < 1))
3966 return false;
3967 break;
3968 default:
3969 return false;
3972 int32_t offset = 0;
3973 const addr_t base_address =
3974 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3975 if (!success)
3976 return false;
3978 EmulateInstruction::Context context;
3979 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3980 std::optional<RegisterInfo> dwarf_reg =
3981 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
3982 context.SetRegisterPlusOffset(*dwarf_reg, offset);
3984 for (int i = 0; i < 14; ++i) {
3985 if (BitIsSet(registers, i)) {
3986 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3987 context.SetRegisterPlusOffset(*dwarf_reg, offset);
3988 if (wback && (n == 13)) // Pop Instruction
3990 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3991 context.SetAddress(base_address + offset);
3994 // R[i] = MemA [address, 4]; address = address + 4;
3995 uint32_t data = MemARead(context, base_address + offset, addr_byte_size,
3996 0, &success);
3997 if (!success)
3998 return false;
4000 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4001 data))
4002 return false;
4004 offset += addr_byte_size;
4008 if (BitIsSet(registers, 15)) {
4009 // LoadWritePC (MemA [address, 4]);
4010 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4011 context.SetRegisterPlusOffset(*dwarf_reg, offset);
4012 uint32_t data =
4013 MemARead(context, base_address + offset, addr_byte_size, 0, &success);
4014 if (!success)
4015 return false;
4016 // In ARMv5T and above, this is an interworking branch.
4017 if (!LoadWritePC(context, data))
4018 return false;
4021 if (wback && BitIsClear(registers, n)) {
4022 // R[n] = R[n] + 4 * BitCount (registers)
4023 int32_t offset = addr_byte_size * BitCount(registers);
4024 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4025 context.SetRegisterPlusOffset(*dwarf_reg, offset);
4027 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4028 base_address + offset))
4029 return false;
4031 if (wback && BitIsSet(registers, n))
4032 // R[n] bits(32) UNKNOWN;
4033 return WriteBits32Unknown(n);
4035 return true;
4038 // LDMDA loads multiple registers from consecutive memory locations using an
4039 // address from a base register.
4040 // The consecutive memory locations end at this address and the address just
4041 // below the lowest of those locations can optionally be written back to the
4042 // base register.
4043 bool EmulateInstructionARM::EmulateLDMDA(const uint32_t opcode,
4044 const ARMEncoding encoding) {
4045 #if 0
4046 // ARM pseudo code...
4047 if ConditionPassed() then
4048 EncodingSpecificOperations();
4049 address = R[n] - 4*BitCount(registers) + 4;
4051 for i = 0 to 14
4052 if registers<i> == '1' then
4053 R[i] = MemA[address,4]; address = address + 4;
4055 if registers<15> == '1' then
4056 LoadWritePC(MemA[address,4]);
4058 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4059 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4060 #endif
4062 bool success = false;
4064 if (ConditionPassed(opcode)) {
4065 uint32_t n;
4066 uint32_t registers = 0;
4067 bool wback;
4068 const uint32_t addr_byte_size = GetAddressByteSize();
4070 // EncodingSpecificOperations();
4071 switch (encoding) {
4072 case eEncodingA1:
4073 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4074 n = Bits32(opcode, 19, 16);
4075 registers = Bits32(opcode, 15, 0);
4076 wback = BitIsSet(opcode, 21);
4078 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4079 if ((n == 15) || (BitCount(registers) < 1))
4080 return false;
4082 break;
4084 default:
4085 return false;
4087 // address = R[n] - 4*BitCount(registers) + 4;
4089 int32_t offset = 0;
4090 addr_t Rn = ReadCoreReg(n, &success);
4092 if (!success)
4093 return false;
4095 addr_t address =
4096 Rn - (addr_byte_size * BitCount(registers)) + addr_byte_size;
4098 EmulateInstruction::Context context;
4099 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4100 std::optional<RegisterInfo> dwarf_reg =
4101 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
4102 context.SetRegisterPlusOffset(*dwarf_reg, offset);
4104 // for i = 0 to 14
4105 for (int i = 0; i < 14; ++i) {
4106 // if registers<i> == '1' then
4107 if (BitIsSet(registers, i)) {
4108 // R[i] = MemA[address,4]; address = address + 4;
4109 context.SetRegisterPlusOffset(*dwarf_reg, Rn - (address + offset));
4110 uint32_t data =
4111 MemARead(context, address + offset, addr_byte_size, 0, &success);
4112 if (!success)
4113 return false;
4114 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4115 data))
4116 return false;
4117 offset += addr_byte_size;
4121 // if registers<15> == '1' then
4122 // LoadWritePC(MemA[address,4]);
4123 if (BitIsSet(registers, 15)) {
4124 context.SetRegisterPlusOffset(*dwarf_reg, offset);
4125 uint32_t data =
4126 MemARead(context, address + offset, addr_byte_size, 0, &success);
4127 if (!success)
4128 return false;
4129 // In ARMv5T and above, this is an interworking branch.
4130 if (!LoadWritePC(context, data))
4131 return false;
4134 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4135 if (wback && BitIsClear(registers, n)) {
4137 offset = (addr_byte_size * BitCount(registers)) * -1;
4138 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4139 context.SetImmediateSigned(offset);
4140 addr_t addr = Rn + offset;
4141 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4142 addr))
4143 return false;
4146 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4147 if (wback && BitIsSet(registers, n))
4148 return WriteBits32Unknown(n);
4150 return true;
4153 // LDMDB loads multiple registers from consecutive memory locations using an
4154 // address from a base register. The
4155 // consecutive memory locations end just below this address, and the address of
4156 // the lowest of those locations can be optionally written back to the base
4157 // register.
4158 bool EmulateInstructionARM::EmulateLDMDB(const uint32_t opcode,
4159 const ARMEncoding encoding) {
4160 #if 0
4161 // ARM pseudo code...
4162 if ConditionPassed() then
4163 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4164 address = R[n] - 4*BitCount(registers);
4166 for i = 0 to 14
4167 if registers<i> == '1' then
4168 R[i] = MemA[address,4]; address = address + 4;
4169 if registers<15> == '1' then
4170 LoadWritePC(MemA[address,4]);
4172 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4173 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
4174 #endif
4176 bool success = false;
4178 if (ConditionPassed(opcode)) {
4179 uint32_t n;
4180 uint32_t registers = 0;
4181 bool wback;
4182 const uint32_t addr_byte_size = GetAddressByteSize();
4183 switch (encoding) {
4184 case eEncodingT1:
4185 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
4186 n = Bits32(opcode, 19, 16);
4187 registers = Bits32(opcode, 15, 0);
4188 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
4189 wback = BitIsSet(opcode, 21);
4191 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then
4192 // UNPREDICTABLE;
4193 if ((n == 15) || (BitCount(registers) < 2) ||
4194 (BitIsSet(opcode, 14) && BitIsSet(opcode, 15)))
4195 return false;
4197 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
4198 // UNPREDICTABLE;
4199 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
4200 return false;
4202 // if wback && registers<n> == '1' then UNPREDICTABLE;
4203 if (wback && BitIsSet(registers, n))
4204 return false;
4206 break;
4208 case eEncodingA1:
4209 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4210 n = Bits32(opcode, 19, 16);
4211 registers = Bits32(opcode, 15, 0);
4212 wback = BitIsSet(opcode, 21);
4214 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4215 if ((n == 15) || (BitCount(registers) < 1))
4216 return false;
4218 break;
4220 default:
4221 return false;
4224 // address = R[n] - 4*BitCount(registers);
4226 int32_t offset = 0;
4227 addr_t Rn =
4228 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4230 if (!success)
4231 return false;
4233 addr_t address = Rn - (addr_byte_size * BitCount(registers));
4234 EmulateInstruction::Context context;
4235 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4236 std::optional<RegisterInfo> dwarf_reg =
4237 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
4238 context.SetRegisterPlusOffset(*dwarf_reg, Rn - address);
4240 for (int i = 0; i < 14; ++i) {
4241 if (BitIsSet(registers, i)) {
4242 // R[i] = MemA[address,4]; address = address + 4;
4243 context.SetRegisterPlusOffset(*dwarf_reg, Rn - (address + offset));
4244 uint32_t data =
4245 MemARead(context, address + offset, addr_byte_size, 0, &success);
4246 if (!success)
4247 return false;
4249 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4250 data))
4251 return false;
4253 offset += addr_byte_size;
4257 // if registers<15> == '1' then
4258 // LoadWritePC(MemA[address,4]);
4259 if (BitIsSet(registers, 15)) {
4260 context.SetRegisterPlusOffset(*dwarf_reg, offset);
4261 uint32_t data =
4262 MemARead(context, address + offset, addr_byte_size, 0, &success);
4263 if (!success)
4264 return false;
4265 // In ARMv5T and above, this is an interworking branch.
4266 if (!LoadWritePC(context, data))
4267 return false;
4270 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4271 if (wback && BitIsClear(registers, n)) {
4273 offset = (addr_byte_size * BitCount(registers)) * -1;
4274 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4275 context.SetImmediateSigned(offset);
4276 addr_t addr = Rn + offset;
4277 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4278 addr))
4279 return false;
4282 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only
4283 // possible for encoding A1
4284 if (wback && BitIsSet(registers, n))
4285 return WriteBits32Unknown(n);
4287 return true;
4290 // LDMIB loads multiple registers from consecutive memory locations using an
4291 // address from a base register. The
4292 // consecutive memory locations start just above this address, and thea ddress
4293 // of the last of those locations can optinoally be written back to the base
4294 // register.
4295 bool EmulateInstructionARM::EmulateLDMIB(const uint32_t opcode,
4296 const ARMEncoding encoding) {
4297 #if 0
4298 if ConditionPassed() then
4299 EncodingSpecificOperations();
4300 address = R[n] + 4;
4302 for i = 0 to 14
4303 if registers<i> == '1' then
4304 R[i] = MemA[address,4]; address = address + 4;
4305 if registers<15> == '1' then
4306 LoadWritePC(MemA[address,4]);
4308 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
4309 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4310 #endif
4312 bool success = false;
4314 if (ConditionPassed(opcode)) {
4315 uint32_t n;
4316 uint32_t registers = 0;
4317 bool wback;
4318 const uint32_t addr_byte_size = GetAddressByteSize();
4319 switch (encoding) {
4320 case eEncodingA1:
4321 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4322 n = Bits32(opcode, 19, 16);
4323 registers = Bits32(opcode, 15, 0);
4324 wback = BitIsSet(opcode, 21);
4326 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4327 if ((n == 15) || (BitCount(registers) < 1))
4328 return false;
4330 break;
4331 default:
4332 return false;
4334 // address = R[n] + 4;
4336 int32_t offset = 0;
4337 addr_t Rn =
4338 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4340 if (!success)
4341 return false;
4343 addr_t address = Rn + addr_byte_size;
4345 EmulateInstruction::Context context;
4346 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4347 std::optional<RegisterInfo> dwarf_reg =
4348 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
4349 context.SetRegisterPlusOffset(*dwarf_reg, offset);
4351 for (int i = 0; i < 14; ++i) {
4352 if (BitIsSet(registers, i)) {
4353 // R[i] = MemA[address,4]; address = address + 4;
4355 context.SetRegisterPlusOffset(*dwarf_reg, offset + addr_byte_size);
4356 uint32_t data =
4357 MemARead(context, address + offset, addr_byte_size, 0, &success);
4358 if (!success)
4359 return false;
4361 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4362 data))
4363 return false;
4365 offset += addr_byte_size;
4369 // if registers<15> == '1' then
4370 // LoadWritePC(MemA[address,4]);
4371 if (BitIsSet(registers, 15)) {
4372 context.SetRegisterPlusOffset(*dwarf_reg, offset);
4373 uint32_t data =
4374 MemARead(context, address + offset, addr_byte_size, 0, &success);
4375 if (!success)
4376 return false;
4377 // In ARMv5T and above, this is an interworking branch.
4378 if (!LoadWritePC(context, data))
4379 return false;
4382 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
4383 if (wback && BitIsClear(registers, n)) {
4385 offset = addr_byte_size * BitCount(registers);
4386 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4387 context.SetImmediateSigned(offset);
4388 addr_t addr = Rn + offset;
4389 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4390 addr))
4391 return false;
4394 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only
4395 // possible for encoding A1
4396 if (wback && BitIsSet(registers, n))
4397 return WriteBits32Unknown(n);
4399 return true;
4402 // Load Register (immediate) calculates an address from a base register value
4403 // and an immediate offset, loads a word from memory, and writes to a register.
4404 // LDR (immediate, Thumb)
4405 bool EmulateInstructionARM::EmulateLDRRtRnImm(const uint32_t opcode,
4406 const ARMEncoding encoding) {
4407 #if 0
4408 // ARM pseudo code...
4409 if (ConditionPassed())
4411 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
4412 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4413 address = if index then offset_addr else R[n];
4414 data = MemU[address,4];
4415 if wback then R[n] = offset_addr;
4416 if t == 15 then
4417 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
4418 elsif UnalignedSupport() || address<1:0> = '00' then
4419 R[t] = data;
4420 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
4422 #endif
4424 bool success = false;
4426 if (ConditionPassed(opcode)) {
4427 uint32_t Rt; // the destination register
4428 uint32_t Rn; // the base register
4429 uint32_t imm32; // the immediate offset used to form the address
4430 addr_t offset_addr; // the offset address
4431 addr_t address; // the calculated address
4432 uint32_t data; // the literal data value from memory load
4433 bool add, index, wback;
4434 switch (encoding) {
4435 case eEncodingT1:
4436 Rt = Bits32(opcode, 2, 0);
4437 Rn = Bits32(opcode, 5, 3);
4438 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
4439 // index = TRUE; add = TRUE; wback = FALSE
4440 add = true;
4441 index = true;
4442 wback = false;
4444 break;
4446 case eEncodingT2:
4447 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
4448 Rt = Bits32(opcode, 10, 8);
4449 Rn = 13;
4450 imm32 = Bits32(opcode, 7, 0) << 2;
4452 // index = TRUE; add = TRUE; wback = FALSE;
4453 index = true;
4454 add = true;
4455 wback = false;
4457 break;
4459 case eEncodingT3:
4460 // if Rn == '1111' then SEE LDR (literal);
4461 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4462 Rt = Bits32(opcode, 15, 12);
4463 Rn = Bits32(opcode, 19, 16);
4464 imm32 = Bits32(opcode, 11, 0);
4466 // index = TRUE; add = TRUE; wback = FALSE;
4467 index = true;
4468 add = true;
4469 wback = false;
4471 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
4472 if ((Rt == 15) && InITBlock() && !LastInITBlock())
4473 return false;
4475 break;
4477 case eEncodingT4:
4478 // if Rn == '1111' then SEE LDR (literal);
4479 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
4480 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 ==
4481 // '00000100' then SEE POP;
4482 // if P == '0' && W == '0' then UNDEFINED;
4483 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
4484 return false;
4486 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4487 Rt = Bits32(opcode, 15, 12);
4488 Rn = Bits32(opcode, 19, 16);
4489 imm32 = Bits32(opcode, 7, 0);
4491 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
4492 index = BitIsSet(opcode, 10);
4493 add = BitIsSet(opcode, 9);
4494 wback = BitIsSet(opcode, 8);
4496 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock())
4497 // then UNPREDICTABLE;
4498 if ((wback && (Rn == Rt)) ||
4499 ((Rt == 15) && InITBlock() && !LastInITBlock()))
4500 return false;
4502 break;
4504 default:
4505 return false;
4507 uint32_t base = ReadCoreReg(Rn, &success);
4508 if (!success)
4509 return false;
4510 if (add)
4511 offset_addr = base + imm32;
4512 else
4513 offset_addr = base - imm32;
4515 address = (index ? offset_addr : base);
4517 std::optional<RegisterInfo> base_reg =
4518 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn);
4519 if (wback) {
4520 EmulateInstruction::Context ctx;
4521 if (Rn == 13) {
4522 ctx.type = eContextAdjustStackPointer;
4523 ctx.SetImmediateSigned((int32_t)(offset_addr - base));
4524 } else if (Rn == GetFramePointerRegisterNumber()) {
4525 ctx.type = eContextSetFramePointer;
4526 ctx.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base));
4527 } else {
4528 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
4529 ctx.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base));
4532 if (!WriteRegisterUnsigned(ctx, eRegisterKindDWARF, dwarf_r0 + Rn,
4533 offset_addr))
4534 return false;
4537 // Prepare to write to the Rt register.
4538 EmulateInstruction::Context context;
4539 context.type = EmulateInstruction::eContextRegisterLoad;
4540 context.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base));
4542 // Read memory from the address.
4543 data = MemURead(context, address, 4, 0, &success);
4544 if (!success)
4545 return false;
4547 if (Rt == 15) {
4548 if (Bits32(address, 1, 0) == 0) {
4549 if (!LoadWritePC(context, data))
4550 return false;
4551 } else
4552 return false;
4553 } else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) {
4554 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rt,
4555 data))
4556 return false;
4557 } else
4558 WriteBits32Unknown(Rt);
4560 return true;
4563 // STM (Store Multiple Increment After) stores multiple registers to consecutive
4564 // memory locations using an address
4565 // from a base register. The consecutive memory locations start at this
4566 // address, and the address just above the last of those locations can
4567 // optionally be written back to the base register.
4568 bool EmulateInstructionARM::EmulateSTM(const uint32_t opcode,
4569 const ARMEncoding encoding) {
4570 #if 0
4571 if ConditionPassed() then
4572 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4573 address = R[n];
4575 for i = 0 to 14
4576 if registers<i> == '1' then
4577 if i == n && wback && i != LowestSetBit(registers) then
4578 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
4579 else
4580 MemA[address,4] = R[i];
4581 address = address + 4;
4583 if registers<15> == '1' then // Only possible for encoding A1
4584 MemA[address,4] = PCStoreValue();
4585 if wback then R[n] = R[n] + 4*BitCount(registers);
4586 #endif
4588 bool success = false;
4590 if (ConditionPassed(opcode)) {
4591 uint32_t n;
4592 uint32_t registers = 0;
4593 bool wback;
4594 const uint32_t addr_byte_size = GetAddressByteSize();
4596 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4597 switch (encoding) {
4598 case eEncodingT1:
4599 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
4600 n = Bits32(opcode, 10, 8);
4601 registers = Bits32(opcode, 7, 0);
4602 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
4603 wback = true;
4605 // if BitCount(registers) < 1 then UNPREDICTABLE;
4606 if (BitCount(registers) < 1)
4607 return false;
4609 break;
4611 case eEncodingT2:
4612 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4613 n = Bits32(opcode, 19, 16);
4614 registers = Bits32(opcode, 15, 0);
4615 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4616 wback = BitIsSet(opcode, 21);
4618 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4619 if ((n == 15) || (BitCount(registers) < 2))
4620 return false;
4622 // if wback && registers<n> == '1' then UNPREDICTABLE;
4623 if (wback && BitIsSet(registers, n))
4624 return false;
4626 break;
4628 case eEncodingA1:
4629 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4630 n = Bits32(opcode, 19, 16);
4631 registers = Bits32(opcode, 15, 0);
4632 wback = BitIsSet(opcode, 21);
4634 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4635 if ((n == 15) || (BitCount(registers) < 1))
4636 return false;
4638 break;
4640 default:
4641 return false;
4644 // address = R[n];
4645 int32_t offset = 0;
4646 const addr_t address =
4647 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4648 if (!success)
4649 return false;
4651 EmulateInstruction::Context context;
4652 context.type = EmulateInstruction::eContextRegisterStore;
4653 std::optional<RegisterInfo> base_reg =
4654 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
4656 // for i = 0 to 14
4657 uint32_t lowest_set_bit = 14;
4658 for (uint32_t i = 0; i < 14; ++i) {
4659 // if registers<i> == '1' then
4660 if (BitIsSet(registers, i)) {
4661 if (i < lowest_set_bit)
4662 lowest_set_bit = i;
4663 // if i == n && wback && i != LowestSetBit(registers) then
4664 if ((i == n) && wback && (i != lowest_set_bit))
4665 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings
4666 // T1 and A1
4667 WriteBits32UnknownToMemory(address + offset);
4668 else {
4669 // MemA[address,4] = R[i];
4670 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
4671 0, &success);
4672 if (!success)
4673 return false;
4675 std::optional<RegisterInfo> data_reg =
4676 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i);
4677 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, offset);
4678 if (!MemAWrite(context, address + offset, data, addr_byte_size))
4679 return false;
4682 // address = address + 4;
4683 offset += addr_byte_size;
4687 // if registers<15> == '1' then // Only possible for encoding A1
4688 // MemA[address,4] = PCStoreValue();
4689 if (BitIsSet(registers, 15)) {
4690 std::optional<RegisterInfo> pc_reg =
4691 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);
4692 context.SetRegisterPlusOffset(*pc_reg, 8);
4693 const uint32_t pc = ReadCoreReg(PC_REG, &success);
4694 if (!success)
4695 return false;
4697 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4698 return false;
4701 // if wback then R[n] = R[n] + 4*BitCount(registers);
4702 if (wback) {
4703 offset = addr_byte_size * BitCount(registers);
4704 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4705 context.SetImmediateSigned(offset);
4706 addr_t data = address + offset;
4707 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4708 data))
4709 return false;
4712 return true;
4715 // STMDA (Store Multiple Decrement After) stores multiple registers to
4716 // consecutive memory locations using an address from a base register. The
4717 // consecutive memory locations end at this address, and the address just below
4718 // the lowest of those locations can optionally be written back to the base
4719 // register.
4720 bool EmulateInstructionARM::EmulateSTMDA(const uint32_t opcode,
4721 const ARMEncoding encoding) {
4722 #if 0
4723 if ConditionPassed() then
4724 EncodingSpecificOperations();
4725 address = R[n] - 4*BitCount(registers) + 4;
4727 for i = 0 to 14
4728 if registers<i> == '1' then
4729 if i == n && wback && i != LowestSetBit(registers) then
4730 MemA[address,4] = bits(32) UNKNOWN;
4731 else
4732 MemA[address,4] = R[i];
4733 address = address + 4;
4735 if registers<15> == '1' then
4736 MemA[address,4] = PCStoreValue();
4738 if wback then R[n] = R[n] - 4*BitCount(registers);
4739 #endif
4741 bool success = false;
4743 if (ConditionPassed(opcode)) {
4744 uint32_t n;
4745 uint32_t registers = 0;
4746 bool wback;
4747 const uint32_t addr_byte_size = GetAddressByteSize();
4749 // EncodingSpecificOperations();
4750 switch (encoding) {
4751 case eEncodingA1:
4752 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4753 n = Bits32(opcode, 19, 16);
4754 registers = Bits32(opcode, 15, 0);
4755 wback = BitIsSet(opcode, 21);
4757 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4758 if ((n == 15) || (BitCount(registers) < 1))
4759 return false;
4760 break;
4761 default:
4762 return false;
4765 // address = R[n] - 4*BitCount(registers) + 4;
4766 int32_t offset = 0;
4767 addr_t Rn = ReadCoreReg(n, &success);
4768 if (!success)
4769 return false;
4771 addr_t address = Rn - (addr_byte_size * BitCount(registers)) + 4;
4773 EmulateInstruction::Context context;
4774 context.type = EmulateInstruction::eContextRegisterStore;
4775 std::optional<RegisterInfo> base_reg =
4776 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
4778 // for i = 0 to 14
4779 uint32_t lowest_bit_set = 14;
4780 for (uint32_t i = 0; i < 14; ++i) {
4781 // if registers<i> == '1' then
4782 if (BitIsSet(registers, i)) {
4783 if (i < lowest_bit_set)
4784 lowest_bit_set = i;
4785 // if i == n && wback && i != LowestSetBit(registers) then
4786 if ((i == n) && wback && (i != lowest_bit_set))
4787 // MemA[address,4] = bits(32) UNKNOWN;
4788 WriteBits32UnknownToMemory(address + offset);
4789 else {
4790 // MemA[address,4] = R[i];
4791 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
4792 0, &success);
4793 if (!success)
4794 return false;
4796 std::optional<RegisterInfo> data_reg =
4797 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i);
4798 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
4799 Rn - (address + offset));
4800 if (!MemAWrite(context, address + offset, data, addr_byte_size))
4801 return false;
4804 // address = address + 4;
4805 offset += addr_byte_size;
4809 // if registers<15> == '1' then
4810 // MemA[address,4] = PCStoreValue();
4811 if (BitIsSet(registers, 15)) {
4812 std::optional<RegisterInfo> pc_reg =
4813 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);
4814 context.SetRegisterPlusOffset(*pc_reg, 8);
4815 const uint32_t pc = ReadCoreReg(PC_REG, &success);
4816 if (!success)
4817 return false;
4819 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4820 return false;
4823 // if wback then R[n] = R[n] - 4*BitCount(registers);
4824 if (wback) {
4825 offset = (addr_byte_size * BitCount(registers)) * -1;
4826 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4827 context.SetImmediateSigned(offset);
4828 addr_t data = Rn + offset;
4829 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4830 data))
4831 return false;
4834 return true;
4837 // STMDB (Store Multiple Decrement Before) stores multiple registers to
4838 // consecutive memory locations using an address from a base register. The
4839 // consecutive memory locations end just below this address, and the address of
4840 // the first of those locations can optionally be written back to the base
4841 // register.
4842 bool EmulateInstructionARM::EmulateSTMDB(const uint32_t opcode,
4843 const ARMEncoding encoding) {
4844 #if 0
4845 if ConditionPassed() then
4846 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4847 address = R[n] - 4*BitCount(registers);
4849 for i = 0 to 14
4850 if registers<i> == '1' then
4851 if i == n && wback && i != LowestSetBit(registers) then
4852 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4853 else
4854 MemA[address,4] = R[i];
4855 address = address + 4;
4857 if registers<15> == '1' then // Only possible for encoding A1
4858 MemA[address,4] = PCStoreValue();
4860 if wback then R[n] = R[n] - 4*BitCount(registers);
4861 #endif
4863 bool success = false;
4865 if (ConditionPassed(opcode)) {
4866 uint32_t n;
4867 uint32_t registers = 0;
4868 bool wback;
4869 const uint32_t addr_byte_size = GetAddressByteSize();
4871 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4872 switch (encoding) {
4873 case eEncodingT1:
4874 // if W == '1' && Rn == '1101' then SEE PUSH;
4875 if ((BitIsSet(opcode, 21)) && (Bits32(opcode, 19, 16) == 13)) {
4876 // See PUSH
4878 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4879 n = Bits32(opcode, 19, 16);
4880 registers = Bits32(opcode, 15, 0);
4881 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4882 wback = BitIsSet(opcode, 21);
4883 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4884 if ((n == 15) || BitCount(registers) < 2)
4885 return false;
4886 // if wback && registers<n> == '1' then UNPREDICTABLE;
4887 if (wback && BitIsSet(registers, n))
4888 return false;
4889 break;
4891 case eEncodingA1:
4892 // if W == '1' && Rn == '1101' && BitCount(register_list) >= 2 then SEE
4893 // PUSH;
4894 if (BitIsSet(opcode, 21) && (Bits32(opcode, 19, 16) == 13) &&
4895 BitCount(Bits32(opcode, 15, 0)) >= 2) {
4896 // See Push
4898 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4899 n = Bits32(opcode, 19, 16);
4900 registers = Bits32(opcode, 15, 0);
4901 wback = BitIsSet(opcode, 21);
4902 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4903 if ((n == 15) || BitCount(registers) < 1)
4904 return false;
4905 break;
4907 default:
4908 return false;
4911 // address = R[n] - 4*BitCount(registers);
4913 int32_t offset = 0;
4914 addr_t Rn =
4915 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4916 if (!success)
4917 return false;
4919 addr_t address = Rn - (addr_byte_size * BitCount(registers));
4921 EmulateInstruction::Context context;
4922 context.type = EmulateInstruction::eContextRegisterStore;
4923 std::optional<RegisterInfo> base_reg =
4924 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
4926 // for i = 0 to 14
4927 uint32_t lowest_set_bit = 14;
4928 for (uint32_t i = 0; i < 14; ++i) {
4929 // if registers<i> == '1' then
4930 if (BitIsSet(registers, i)) {
4931 if (i < lowest_set_bit)
4932 lowest_set_bit = i;
4933 // if i == n && wback && i != LowestSetBit(registers) then
4934 if ((i == n) && wback && (i != lowest_set_bit))
4935 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding
4936 // A1
4937 WriteBits32UnknownToMemory(address + offset);
4938 else {
4939 // MemA[address,4] = R[i];
4940 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
4941 0, &success);
4942 if (!success)
4943 return false;
4945 std::optional<RegisterInfo> data_reg =
4946 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i);
4947 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
4948 Rn - (address + offset));
4949 if (!MemAWrite(context, address + offset, data, addr_byte_size))
4950 return false;
4953 // address = address + 4;
4954 offset += addr_byte_size;
4958 // if registers<15> == '1' then // Only possible for encoding A1
4959 // MemA[address,4] = PCStoreValue();
4960 if (BitIsSet(registers, 15)) {
4961 std::optional<RegisterInfo> pc_reg =
4962 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);
4963 context.SetRegisterPlusOffset(*pc_reg, 8);
4964 const uint32_t pc = ReadCoreReg(PC_REG, &success);
4965 if (!success)
4966 return false;
4968 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4969 return false;
4972 // if wback then R[n] = R[n] - 4*BitCount(registers);
4973 if (wback) {
4974 offset = (addr_byte_size * BitCount(registers)) * -1;
4975 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4976 context.SetImmediateSigned(offset);
4977 addr_t data = Rn + offset;
4978 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4979 data))
4980 return false;
4983 return true;
4986 // STMIB (Store Multiple Increment Before) stores multiple registers to
4987 // consecutive memory locations using an address from a base register. The
4988 // consecutive memory locations start just above this address, and the address
4989 // of the last of those locations can optionally be written back to the base
4990 // register.
4991 bool EmulateInstructionARM::EmulateSTMIB(const uint32_t opcode,
4992 const ARMEncoding encoding) {
4993 #if 0
4994 if ConditionPassed() then
4995 EncodingSpecificOperations();
4996 address = R[n] + 4;
4998 for i = 0 to 14
4999 if registers<i> == '1' then
5000 if i == n && wback && i != LowestSetBit(registers) then
5001 MemA[address,4] = bits(32) UNKNOWN;
5002 else
5003 MemA[address,4] = R[i];
5004 address = address + 4;
5006 if registers<15> == '1' then
5007 MemA[address,4] = PCStoreValue();
5009 if wback then R[n] = R[n] + 4*BitCount(registers);
5010 #endif
5012 bool success = false;
5014 if (ConditionPassed(opcode)) {
5015 uint32_t n;
5016 uint32_t registers = 0;
5017 bool wback;
5018 const uint32_t addr_byte_size = GetAddressByteSize();
5020 // EncodingSpecificOperations();
5021 switch (encoding) {
5022 case eEncodingA1:
5023 // n = UInt(Rn); registers = register_list; wback = (W == '1');
5024 n = Bits32(opcode, 19, 16);
5025 registers = Bits32(opcode, 15, 0);
5026 wback = BitIsSet(opcode, 21);
5028 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
5029 if ((n == 15) && (BitCount(registers) < 1))
5030 return false;
5031 break;
5032 default:
5033 return false;
5035 // address = R[n] + 4;
5037 int32_t offset = 0;
5038 addr_t Rn = ReadCoreReg(n, &success);
5039 if (!success)
5040 return false;
5042 addr_t address = Rn + addr_byte_size;
5044 EmulateInstruction::Context context;
5045 context.type = EmulateInstruction::eContextRegisterStore;
5046 std::optional<RegisterInfo> base_reg =
5047 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
5049 uint32_t lowest_set_bit = 14;
5050 // for i = 0 to 14
5051 for (uint32_t i = 0; i < 14; ++i) {
5052 // if registers<i> == '1' then
5053 if (BitIsSet(registers, i)) {
5054 if (i < lowest_set_bit)
5055 lowest_set_bit = i;
5056 // if i == n && wback && i != LowestSetBit(registers) then
5057 if ((i == n) && wback && (i != lowest_set_bit))
5058 // MemA[address,4] = bits(32) UNKNOWN;
5059 WriteBits32UnknownToMemory(address + offset);
5060 // else
5061 else {
5062 // MemA[address,4] = R[i];
5063 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
5064 0, &success);
5065 if (!success)
5066 return false;
5068 std::optional<RegisterInfo> data_reg =
5069 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i);
5070 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
5071 offset + addr_byte_size);
5072 if (!MemAWrite(context, address + offset, data, addr_byte_size))
5073 return false;
5076 // address = address + 4;
5077 offset += addr_byte_size;
5081 // if registers<15> == '1' then
5082 // MemA[address,4] = PCStoreValue();
5083 if (BitIsSet(registers, 15)) {
5084 std::optional<RegisterInfo> pc_reg =
5085 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);
5086 context.SetRegisterPlusOffset(*pc_reg, 8);
5087 const uint32_t pc = ReadCoreReg(PC_REG, &success);
5088 if (!success)
5089 return false;
5091 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
5092 return false;
5095 // if wback then R[n] = R[n] + 4*BitCount(registers);
5096 if (wback) {
5097 offset = addr_byte_size * BitCount(registers);
5098 context.type = EmulateInstruction::eContextAdjustBaseRegister;
5099 context.SetImmediateSigned(offset);
5100 addr_t data = Rn + offset;
5101 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5102 data))
5103 return false;
5106 return true;
5109 // STR (store immediate) calculates an address from a base register value and an
5110 // immediate offset, and stores a word
5111 // from a register to memory. It can use offset, post-indexed, or pre-indexed
5112 // addressing.
5113 bool EmulateInstructionARM::EmulateSTRThumb(const uint32_t opcode,
5114 const ARMEncoding encoding) {
5115 #if 0
5116 if ConditionPassed() then
5117 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5118 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5119 address = if index then offset_addr else R[n];
5120 if UnalignedSupport() || address<1:0> == '00' then
5121 MemU[address,4] = R[t];
5122 else // Can only occur before ARMv7
5123 MemU[address,4] = bits(32) UNKNOWN;
5124 if wback then R[n] = offset_addr;
5125 #endif
5127 bool success = false;
5129 if (ConditionPassed(opcode)) {
5130 const uint32_t addr_byte_size = GetAddressByteSize();
5132 uint32_t t;
5133 uint32_t n;
5134 uint32_t imm32;
5135 bool index;
5136 bool add;
5137 bool wback;
5138 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
5139 switch (encoding) {
5140 case eEncodingT1:
5141 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
5142 t = Bits32(opcode, 2, 0);
5143 n = Bits32(opcode, 5, 3);
5144 imm32 = Bits32(opcode, 10, 6) << 2;
5146 // index = TRUE; add = TRUE; wback = FALSE;
5147 index = true;
5148 add = false;
5149 wback = false;
5150 break;
5152 case eEncodingT2:
5153 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
5154 t = Bits32(opcode, 10, 8);
5155 n = 13;
5156 imm32 = Bits32(opcode, 7, 0) << 2;
5158 // index = TRUE; add = TRUE; wback = FALSE;
5159 index = true;
5160 add = true;
5161 wback = false;
5162 break;
5164 case eEncodingT3:
5165 // if Rn == '1111' then UNDEFINED;
5166 if (Bits32(opcode, 19, 16) == 15)
5167 return false;
5169 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5170 t = Bits32(opcode, 15, 12);
5171 n = Bits32(opcode, 19, 16);
5172 imm32 = Bits32(opcode, 11, 0);
5174 // index = TRUE; add = TRUE; wback = FALSE;
5175 index = true;
5176 add = true;
5177 wback = false;
5179 // if t == 15 then UNPREDICTABLE;
5180 if (t == 15)
5181 return false;
5182 break;
5184 case eEncodingT4:
5185 // if P == '1' && U == '1' && W == '0' then SEE STRT;
5186 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 ==
5187 // '00000100' then SEE PUSH;
5188 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
5189 if ((Bits32(opcode, 19, 16) == 15) ||
5190 (BitIsClear(opcode, 10) && BitIsClear(opcode, 8)))
5191 return false;
5193 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5194 t = Bits32(opcode, 15, 12);
5195 n = Bits32(opcode, 19, 16);
5196 imm32 = Bits32(opcode, 7, 0);
5198 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
5199 index = BitIsSet(opcode, 10);
5200 add = BitIsSet(opcode, 9);
5201 wback = BitIsSet(opcode, 8);
5203 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
5204 if ((t == 15) || (wback && (n == t)))
5205 return false;
5206 break;
5208 default:
5209 return false;
5212 addr_t offset_addr;
5213 addr_t address;
5215 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5216 uint32_t base_address = ReadCoreReg(n, &success);
5217 if (!success)
5218 return false;
5220 if (add)
5221 offset_addr = base_address + imm32;
5222 else
5223 offset_addr = base_address - imm32;
5225 // address = if index then offset_addr else R[n];
5226 if (index)
5227 address = offset_addr;
5228 else
5229 address = base_address;
5231 EmulateInstruction::Context context;
5232 if (n == 13)
5233 context.type = eContextPushRegisterOnStack;
5234 else
5235 context.type = eContextRegisterStore;
5237 std::optional<RegisterInfo> base_reg =
5238 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
5240 // if UnalignedSupport() || address<1:0> == '00' then
5241 if (UnalignedSupport() ||
5242 (BitIsClear(address, 1) && BitIsClear(address, 0))) {
5243 // MemU[address,4] = R[t];
5244 uint32_t data =
5245 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
5246 if (!success)
5247 return false;
5249 std::optional<RegisterInfo> data_reg =
5250 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
5251 int32_t offset = address - base_address;
5252 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, offset);
5253 if (!MemUWrite(context, address, data, addr_byte_size))
5254 return false;
5255 } else {
5256 // MemU[address,4] = bits(32) UNKNOWN;
5257 WriteBits32UnknownToMemory(address);
5260 // if wback then R[n] = offset_addr;
5261 if (wback) {
5262 if (n == 13)
5263 context.type = eContextAdjustStackPointer;
5264 else
5265 context.type = eContextAdjustBaseRegister;
5266 context.SetAddress(offset_addr);
5268 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5269 offset_addr))
5270 return false;
5273 return true;
5276 // STR (Store Register) calculates an address from a base register value and an
5277 // offset register value, stores a
5278 // word from a register to memory. The offset register value can optionally
5279 // be shifted.
5280 bool EmulateInstructionARM::EmulateSTRRegister(const uint32_t opcode,
5281 const ARMEncoding encoding) {
5282 #if 0
5283 if ConditionPassed() then
5284 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5285 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5286 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5287 address = if index then offset_addr else R[n];
5288 if t == 15 then // Only possible for encoding A1
5289 data = PCStoreValue();
5290 else
5291 data = R[t];
5292 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
5293 MemU[address,4] = data;
5294 else // Can only occur before ARMv7
5295 MemU[address,4] = bits(32) UNKNOWN;
5296 if wback then R[n] = offset_addr;
5297 #endif
5299 bool success = false;
5301 if (ConditionPassed(opcode)) {
5302 const uint32_t addr_byte_size = GetAddressByteSize();
5304 uint32_t t;
5305 uint32_t n;
5306 uint32_t m;
5307 ARM_ShifterType shift_t;
5308 uint32_t shift_n;
5309 bool index;
5310 bool add;
5311 bool wback;
5313 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
5314 switch (encoding) {
5315 case eEncodingT1:
5316 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
5317 // in ThumbEE";
5318 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5319 t = Bits32(opcode, 2, 0);
5320 n = Bits32(opcode, 5, 3);
5321 m = Bits32(opcode, 8, 6);
5323 // index = TRUE; add = TRUE; wback = FALSE;
5324 index = true;
5325 add = true;
5326 wback = false;
5328 // (shift_t, shift_n) = (SRType_LSL, 0);
5329 shift_t = SRType_LSL;
5330 shift_n = 0;
5331 break;
5333 case eEncodingT2:
5334 // if Rn == '1111' then UNDEFINED;
5335 if (Bits32(opcode, 19, 16) == 15)
5336 return false;
5338 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5339 t = Bits32(opcode, 15, 12);
5340 n = Bits32(opcode, 19, 16);
5341 m = Bits32(opcode, 3, 0);
5343 // index = TRUE; add = TRUE; wback = FALSE;
5344 index = true;
5345 add = true;
5346 wback = false;
5348 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5349 shift_t = SRType_LSL;
5350 shift_n = Bits32(opcode, 5, 4);
5352 // if t == 15 || BadReg(m) then UNPREDICTABLE;
5353 if ((t == 15) || (BadReg(m)))
5354 return false;
5355 break;
5357 case eEncodingA1: {
5358 // if P == '0' && W == '1' then SEE STRT;
5359 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5360 t = Bits32(opcode, 15, 12);
5361 n = Bits32(opcode, 19, 16);
5362 m = Bits32(opcode, 3, 0);
5364 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
5365 // (W == '1');
5366 index = BitIsSet(opcode, 24);
5367 add = BitIsSet(opcode, 23);
5368 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
5370 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5371 uint32_t typ = Bits32(opcode, 6, 5);
5372 uint32_t imm5 = Bits32(opcode, 11, 7);
5373 shift_n = DecodeImmShift(typ, imm5, shift_t);
5375 // if m == 15 then UNPREDICTABLE;
5376 if (m == 15)
5377 return false;
5379 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5380 if (wback && ((n == 15) || (n == t)))
5381 return false;
5383 break;
5385 default:
5386 return false;
5389 addr_t offset_addr;
5390 addr_t address;
5391 int32_t offset = 0;
5393 addr_t base_address =
5394 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5395 if (!success)
5396 return false;
5398 uint32_t Rm_data =
5399 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5400 if (!success)
5401 return false;
5403 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5404 offset = Shift(Rm_data, shift_t, shift_n, APSR_C, &success);
5405 if (!success)
5406 return false;
5408 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5409 if (add)
5410 offset_addr = base_address + offset;
5411 else
5412 offset_addr = base_address - offset;
5414 // address = if index then offset_addr else R[n];
5415 if (index)
5416 address = offset_addr;
5417 else
5418 address = base_address;
5420 uint32_t data;
5421 // if t == 15 then // Only possible for encoding A1
5422 if (t == 15)
5423 // data = PCStoreValue();
5424 data = ReadCoreReg(PC_REG, &success);
5425 else
5426 // data = R[t];
5427 data =
5428 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
5430 if (!success)
5431 return false;
5433 EmulateInstruction::Context context;
5434 context.type = eContextRegisterStore;
5436 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() ==
5437 // InstrSet_ARM then
5438 if (UnalignedSupport() ||
5439 (BitIsClear(address, 1) && BitIsClear(address, 0)) ||
5440 CurrentInstrSet() == eModeARM) {
5441 // MemU[address,4] = data;
5443 std::optional<RegisterInfo> base_reg =
5444 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
5445 std::optional<RegisterInfo> data_reg =
5446 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
5448 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
5449 address - base_address);
5450 if (!MemUWrite(context, address, data, addr_byte_size))
5451 return false;
5453 } else
5454 // MemU[address,4] = bits(32) UNKNOWN;
5455 WriteBits32UnknownToMemory(address);
5457 // if wback then R[n] = offset_addr;
5458 if (wback) {
5459 context.type = eContextRegisterLoad;
5460 context.SetAddress(offset_addr);
5461 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5462 offset_addr))
5463 return false;
5466 return true;
5469 bool EmulateInstructionARM::EmulateSTRBThumb(const uint32_t opcode,
5470 const ARMEncoding encoding) {
5471 #if 0
5472 if ConditionPassed() then
5473 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5474 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5475 address = if index then offset_addr else R[n];
5476 MemU[address,1] = R[t]<7:0>;
5477 if wback then R[n] = offset_addr;
5478 #endif
5480 bool success = false;
5482 if (ConditionPassed(opcode)) {
5483 uint32_t t;
5484 uint32_t n;
5485 uint32_t imm32;
5486 bool index;
5487 bool add;
5488 bool wback;
5489 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5490 switch (encoding) {
5491 case eEncodingT1:
5492 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5493 t = Bits32(opcode, 2, 0);
5494 n = Bits32(opcode, 5, 3);
5495 imm32 = Bits32(opcode, 10, 6);
5497 // index = TRUE; add = TRUE; wback = FALSE;
5498 index = true;
5499 add = true;
5500 wback = false;
5501 break;
5503 case eEncodingT2:
5504 // if Rn == '1111' then UNDEFINED;
5505 if (Bits32(opcode, 19, 16) == 15)
5506 return false;
5508 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5509 t = Bits32(opcode, 15, 12);
5510 n = Bits32(opcode, 19, 16);
5511 imm32 = Bits32(opcode, 11, 0);
5513 // index = TRUE; add = TRUE; wback = FALSE;
5514 index = true;
5515 add = true;
5516 wback = false;
5518 // if BadReg(t) then UNPREDICTABLE;
5519 if (BadReg(t))
5520 return false;
5521 break;
5523 case eEncodingT3:
5524 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
5525 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
5526 if (Bits32(opcode, 19, 16) == 15)
5527 return false;
5529 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5530 t = Bits32(opcode, 15, 12);
5531 n = Bits32(opcode, 19, 16);
5532 imm32 = Bits32(opcode, 7, 0);
5534 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
5535 index = BitIsSet(opcode, 10);
5536 add = BitIsSet(opcode, 9);
5537 wback = BitIsSet(opcode, 8);
5539 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
5540 if ((BadReg(t)) || (wback && (n == t)))
5541 return false;
5542 break;
5544 default:
5545 return false;
5548 addr_t offset_addr;
5549 addr_t address;
5550 addr_t base_address =
5551 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5552 if (!success)
5553 return false;
5555 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5556 if (add)
5557 offset_addr = base_address + imm32;
5558 else
5559 offset_addr = base_address - imm32;
5561 // address = if index then offset_addr else R[n];
5562 if (index)
5563 address = offset_addr;
5564 else
5565 address = base_address;
5567 // MemU[address,1] = R[t]<7:0>
5568 std::optional<RegisterInfo> base_reg =
5569 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
5570 std::optional<RegisterInfo> data_reg =
5571 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
5573 EmulateInstruction::Context context;
5574 context.type = eContextRegisterStore;
5575 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
5576 address - base_address);
5578 uint32_t data =
5579 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
5580 if (!success)
5581 return false;
5583 data = Bits32(data, 7, 0);
5585 if (!MemUWrite(context, address, data, 1))
5586 return false;
5588 // if wback then R[n] = offset_addr;
5589 if (wback) {
5590 context.type = eContextRegisterLoad;
5591 context.SetAddress(offset_addr);
5592 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5593 offset_addr))
5594 return false;
5598 return true;
5601 // STRH (register) calculates an address from a base register value and an
5602 // offset register value, and stores a
5603 // halfword from a register to memory. The offset register value can be
5604 // shifted left by 0, 1, 2, or 3 bits.
5605 bool EmulateInstructionARM::EmulateSTRHRegister(const uint32_t opcode,
5606 const ARMEncoding encoding) {
5607 #if 0
5608 if ConditionPassed() then
5609 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5610 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5611 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5612 address = if index then offset_addr else R[n];
5613 if UnalignedSupport() || address<0> == '0' then
5614 MemU[address,2] = R[t]<15:0>;
5615 else // Can only occur before ARMv7
5616 MemU[address,2] = bits(16) UNKNOWN;
5617 if wback then R[n] = offset_addr;
5618 #endif
5620 bool success = false;
5622 if (ConditionPassed(opcode)) {
5623 uint32_t t;
5624 uint32_t n;
5625 uint32_t m;
5626 bool index;
5627 bool add;
5628 bool wback;
5629 ARM_ShifterType shift_t;
5630 uint32_t shift_n;
5632 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5633 switch (encoding) {
5634 case eEncodingT1:
5635 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
5636 // in ThumbEE";
5637 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5638 t = Bits32(opcode, 2, 0);
5639 n = Bits32(opcode, 5, 3);
5640 m = Bits32(opcode, 8, 6);
5642 // index = TRUE; add = TRUE; wback = FALSE;
5643 index = true;
5644 add = true;
5645 wback = false;
5647 // (shift_t, shift_n) = (SRType_LSL, 0);
5648 shift_t = SRType_LSL;
5649 shift_n = 0;
5651 break;
5653 case eEncodingT2:
5654 // if Rn == '1111' then UNDEFINED;
5655 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5656 t = Bits32(opcode, 15, 12);
5657 n = Bits32(opcode, 19, 16);
5658 m = Bits32(opcode, 3, 0);
5659 if (n == 15)
5660 return false;
5662 // index = TRUE; add = TRUE; wback = FALSE;
5663 index = true;
5664 add = true;
5665 wback = false;
5667 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5668 shift_t = SRType_LSL;
5669 shift_n = Bits32(opcode, 5, 4);
5671 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
5672 if (BadReg(t) || BadReg(m))
5673 return false;
5675 break;
5677 case eEncodingA1:
5678 // if P == '0' && W == '1' then SEE STRHT;
5679 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5680 t = Bits32(opcode, 15, 12);
5681 n = Bits32(opcode, 19, 16);
5682 m = Bits32(opcode, 3, 0);
5684 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
5685 // (W == '1');
5686 index = BitIsSet(opcode, 24);
5687 add = BitIsSet(opcode, 23);
5688 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
5690 // (shift_t, shift_n) = (SRType_LSL, 0);
5691 shift_t = SRType_LSL;
5692 shift_n = 0;
5694 // if t == 15 || m == 15 then UNPREDICTABLE;
5695 if ((t == 15) || (m == 15))
5696 return false;
5698 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5699 if (wback && ((n == 15) || (n == t)))
5700 return false;
5702 break;
5704 default:
5705 return false;
5708 uint32_t Rm = ReadCoreReg(m, &success);
5709 if (!success)
5710 return false;
5712 uint32_t Rn = ReadCoreReg(n, &success);
5713 if (!success)
5714 return false;
5716 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5717 uint32_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
5718 if (!success)
5719 return false;
5721 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5722 addr_t offset_addr;
5723 if (add)
5724 offset_addr = Rn + offset;
5725 else
5726 offset_addr = Rn - offset;
5728 // address = if index then offset_addr else R[n];
5729 addr_t address;
5730 if (index)
5731 address = offset_addr;
5732 else
5733 address = Rn;
5735 EmulateInstruction::Context context;
5736 context.type = eContextRegisterStore;
5738 // if UnalignedSupport() || address<0> == '0' then
5739 if (UnalignedSupport() || BitIsClear(address, 0)) {
5740 // MemU[address,2] = R[t]<15:0>;
5741 uint32_t Rt = ReadCoreReg(t, &success);
5742 if (!success)
5743 return false;
5745 EmulateInstruction::Context context;
5746 context.type = eContextRegisterStore;
5747 std::optional<RegisterInfo> base_reg =
5748 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
5749 std::optional<RegisterInfo> offset_reg =
5750 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
5751 std::optional<RegisterInfo> data_reg =
5752 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
5753 context.SetRegisterToRegisterPlusIndirectOffset(*base_reg, *offset_reg,
5754 *data_reg);
5756 if (!MemUWrite(context, address, Bits32(Rt, 15, 0), 2))
5757 return false;
5758 } else // Can only occur before ARMv7
5760 // MemU[address,2] = bits(16) UNKNOWN;
5763 // if wback then R[n] = offset_addr;
5764 if (wback) {
5765 context.type = eContextAdjustBaseRegister;
5766 context.SetAddress(offset_addr);
5767 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5768 offset_addr))
5769 return false;
5773 return true;
5776 // Add with Carry (immediate) adds an immediate value and the carry flag value
5777 // to a register value, and writes the result to the destination register. It
5778 // can optionally update the condition flags based on the result.
5779 bool EmulateInstructionARM::EmulateADCImm(const uint32_t opcode,
5780 const ARMEncoding encoding) {
5781 #if 0
5782 // ARM pseudo code...
5783 if ConditionPassed() then
5784 EncodingSpecificOperations();
5785 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5786 if d == 15 then // Can only occur for ARM encoding
5787 ALUWritePC(result); // setflags is always FALSE here
5788 else
5789 R[d] = result;
5790 if setflags then
5791 APSR.N = result<31>;
5792 APSR.Z = IsZeroBit(result);
5793 APSR.C = carry;
5794 APSR.V = overflow;
5795 #endif
5797 bool success = false;
5799 if (ConditionPassed(opcode)) {
5800 uint32_t Rd, Rn;
5801 uint32_t
5802 imm32; // the immediate value to be added to the value obtained from Rn
5803 bool setflags;
5804 switch (encoding) {
5805 case eEncodingT1:
5806 Rd = Bits32(opcode, 11, 8);
5807 Rn = Bits32(opcode, 19, 16);
5808 setflags = BitIsSet(opcode, 20);
5809 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5810 if (BadReg(Rd) || BadReg(Rn))
5811 return false;
5812 break;
5813 case eEncodingA1:
5814 Rd = Bits32(opcode, 15, 12);
5815 Rn = Bits32(opcode, 19, 16);
5816 setflags = BitIsSet(opcode, 20);
5817 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5819 if (Rd == 15 && setflags)
5820 return EmulateSUBSPcLrEtc(opcode, encoding);
5821 break;
5822 default:
5823 return false;
5826 // Read the first operand.
5827 int32_t val1 = ReadCoreReg(Rn, &success);
5828 if (!success)
5829 return false;
5831 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5833 EmulateInstruction::Context context;
5834 context.type = EmulateInstruction::eContextImmediate;
5835 context.SetNoArgs();
5837 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
5838 res.carry_out, res.overflow))
5839 return false;
5841 return true;
5844 // Add with Carry (register) adds a register value, the carry flag value, and
5845 // an optionally-shifted register value, and writes the result to the
5846 // destination register. It can optionally update the condition flags based on
5847 // the result.
5848 bool EmulateInstructionARM::EmulateADCReg(const uint32_t opcode,
5849 const ARMEncoding encoding) {
5850 #if 0
5851 // ARM pseudo code...
5852 if ConditionPassed() then
5853 EncodingSpecificOperations();
5854 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5855 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5856 if d == 15 then // Can only occur for ARM encoding
5857 ALUWritePC(result); // setflags is always FALSE here
5858 else
5859 R[d] = result;
5860 if setflags then
5861 APSR.N = result<31>;
5862 APSR.Z = IsZeroBit(result);
5863 APSR.C = carry;
5864 APSR.V = overflow;
5865 #endif
5867 bool success = false;
5869 if (ConditionPassed(opcode)) {
5870 uint32_t Rd, Rn, Rm;
5871 ARM_ShifterType shift_t;
5872 uint32_t shift_n; // the shift applied to the value read from Rm
5873 bool setflags;
5874 switch (encoding) {
5875 case eEncodingT1:
5876 Rd = Rn = Bits32(opcode, 2, 0);
5877 Rm = Bits32(opcode, 5, 3);
5878 setflags = !InITBlock();
5879 shift_t = SRType_LSL;
5880 shift_n = 0;
5881 break;
5882 case eEncodingT2:
5883 Rd = Bits32(opcode, 11, 8);
5884 Rn = Bits32(opcode, 19, 16);
5885 Rm = Bits32(opcode, 3, 0);
5886 setflags = BitIsSet(opcode, 20);
5887 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5888 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5889 return false;
5890 break;
5891 case eEncodingA1:
5892 Rd = Bits32(opcode, 15, 12);
5893 Rn = Bits32(opcode, 19, 16);
5894 Rm = Bits32(opcode, 3, 0);
5895 setflags = BitIsSet(opcode, 20);
5896 shift_n = DecodeImmShiftARM(opcode, shift_t);
5898 if (Rd == 15 && setflags)
5899 return EmulateSUBSPcLrEtc(opcode, encoding);
5900 break;
5901 default:
5902 return false;
5905 // Read the first operand.
5906 int32_t val1 = ReadCoreReg(Rn, &success);
5907 if (!success)
5908 return false;
5910 // Read the second operand.
5911 int32_t val2 = ReadCoreReg(Rm, &success);
5912 if (!success)
5913 return false;
5915 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
5916 if (!success)
5917 return false;
5918 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5920 EmulateInstruction::Context context;
5921 context.type = EmulateInstruction::eContextImmediate;
5922 context.SetNoArgs();
5924 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
5925 res.carry_out, res.overflow))
5926 return false;
5928 return true;
5931 // This instruction adds an immediate value to the PC value to form a PC-
5932 // relative address, and writes the result to the destination register.
5933 bool EmulateInstructionARM::EmulateADR(const uint32_t opcode,
5934 const ARMEncoding encoding) {
5935 #if 0
5936 // ARM pseudo code...
5937 if ConditionPassed() then
5938 EncodingSpecificOperations();
5939 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5940 if d == 15 then // Can only occur for ARM encodings
5941 ALUWritePC(result);
5942 else
5943 R[d] = result;
5944 #endif
5946 bool success = false;
5948 if (ConditionPassed(opcode)) {
5949 uint32_t Rd;
5950 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5951 bool add;
5952 switch (encoding) {
5953 case eEncodingT1:
5954 Rd = Bits32(opcode, 10, 8);
5955 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5956 add = true;
5957 break;
5958 case eEncodingT2:
5959 case eEncodingT3:
5960 Rd = Bits32(opcode, 11, 8);
5961 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5962 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5963 if (BadReg(Rd))
5964 return false;
5965 break;
5966 case eEncodingA1:
5967 case eEncodingA2:
5968 Rd = Bits32(opcode, 15, 12);
5969 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5970 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5971 break;
5972 default:
5973 return false;
5976 // Read the PC value.
5977 uint32_t pc = ReadCoreReg(PC_REG, &success);
5978 if (!success)
5979 return false;
5981 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5983 EmulateInstruction::Context context;
5984 context.type = EmulateInstruction::eContextImmediate;
5985 context.SetNoArgs();
5987 if (!WriteCoreReg(context, result, Rd))
5988 return false;
5990 return true;
5993 // This instruction performs a bitwise AND of a register value and an immediate
5994 // value, and writes the result to the destination register. It can optionally
5995 // update the condition flags based on the result.
5996 bool EmulateInstructionARM::EmulateANDImm(const uint32_t opcode,
5997 const ARMEncoding encoding) {
5998 #if 0
5999 // ARM pseudo code...
6000 if ConditionPassed() then
6001 EncodingSpecificOperations();
6002 result = R[n] AND imm32;
6003 if d == 15 then // Can only occur for ARM encoding
6004 ALUWritePC(result); // setflags is always FALSE here
6005 else
6006 R[d] = result;
6007 if setflags then
6008 APSR.N = result<31>;
6009 APSR.Z = IsZeroBit(result);
6010 APSR.C = carry;
6011 // APSR.V unchanged
6012 #endif
6014 bool success = false;
6016 if (ConditionPassed(opcode)) {
6017 uint32_t Rd, Rn;
6018 uint32_t
6019 imm32; // the immediate value to be ANDed to the value obtained from Rn
6020 bool setflags;
6021 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6022 switch (encoding) {
6023 case eEncodingT1:
6024 Rd = Bits32(opcode, 11, 8);
6025 Rn = Bits32(opcode, 19, 16);
6026 setflags = BitIsSet(opcode, 20);
6027 imm32 = ThumbExpandImm_C(
6028 opcode, APSR_C,
6029 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6030 // if Rd == '1111' && S == '1' then SEE TST (immediate);
6031 if (Rd == 15 && setflags)
6032 return EmulateTSTImm(opcode, eEncodingT1);
6033 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
6034 return false;
6035 break;
6036 case eEncodingA1:
6037 Rd = Bits32(opcode, 15, 12);
6038 Rn = Bits32(opcode, 19, 16);
6039 setflags = BitIsSet(opcode, 20);
6040 imm32 =
6041 ARMExpandImm_C(opcode, APSR_C,
6042 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6044 if (Rd == 15 && setflags)
6045 return EmulateSUBSPcLrEtc(opcode, encoding);
6046 break;
6047 default:
6048 return false;
6051 // Read the first operand.
6052 uint32_t val1 = ReadCoreReg(Rn, &success);
6053 if (!success)
6054 return false;
6056 uint32_t result = val1 & imm32;
6058 EmulateInstruction::Context context;
6059 context.type = EmulateInstruction::eContextImmediate;
6060 context.SetNoArgs();
6062 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6063 return false;
6065 return true;
6068 // This instruction performs a bitwise AND of a register value and an
6069 // optionally-shifted register value, and writes the result to the destination
6070 // register. It can optionally update the condition flags based on the result.
6071 bool EmulateInstructionARM::EmulateANDReg(const uint32_t opcode,
6072 const ARMEncoding encoding) {
6073 #if 0
6074 // ARM pseudo code...
6075 if ConditionPassed() then
6076 EncodingSpecificOperations();
6077 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6078 result = R[n] AND shifted;
6079 if d == 15 then // Can only occur for ARM encoding
6080 ALUWritePC(result); // setflags is always FALSE here
6081 else
6082 R[d] = result;
6083 if setflags then
6084 APSR.N = result<31>;
6085 APSR.Z = IsZeroBit(result);
6086 APSR.C = carry;
6087 // APSR.V unchanged
6088 #endif
6090 bool success = false;
6092 if (ConditionPassed(opcode)) {
6093 uint32_t Rd, Rn, Rm;
6094 ARM_ShifterType shift_t;
6095 uint32_t shift_n; // the shift applied to the value read from Rm
6096 bool setflags;
6097 uint32_t carry;
6098 switch (encoding) {
6099 case eEncodingT1:
6100 Rd = Rn = Bits32(opcode, 2, 0);
6101 Rm = Bits32(opcode, 5, 3);
6102 setflags = !InITBlock();
6103 shift_t = SRType_LSL;
6104 shift_n = 0;
6105 break;
6106 case eEncodingT2:
6107 Rd = Bits32(opcode, 11, 8);
6108 Rn = Bits32(opcode, 19, 16);
6109 Rm = Bits32(opcode, 3, 0);
6110 setflags = BitIsSet(opcode, 20);
6111 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6112 // if Rd == '1111' && S == '1' then SEE TST (register);
6113 if (Rd == 15 && setflags)
6114 return EmulateTSTReg(opcode, eEncodingT2);
6115 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
6116 return false;
6117 break;
6118 case eEncodingA1:
6119 Rd = Bits32(opcode, 15, 12);
6120 Rn = Bits32(opcode, 19, 16);
6121 Rm = Bits32(opcode, 3, 0);
6122 setflags = BitIsSet(opcode, 20);
6123 shift_n = DecodeImmShiftARM(opcode, shift_t);
6125 if (Rd == 15 && setflags)
6126 return EmulateSUBSPcLrEtc(opcode, encoding);
6127 break;
6128 default:
6129 return false;
6132 // Read the first operand.
6133 uint32_t val1 = ReadCoreReg(Rn, &success);
6134 if (!success)
6135 return false;
6137 // Read the second operand.
6138 uint32_t val2 = ReadCoreReg(Rm, &success);
6139 if (!success)
6140 return false;
6142 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
6143 if (!success)
6144 return false;
6145 uint32_t result = val1 & shifted;
6147 EmulateInstruction::Context context;
6148 context.type = EmulateInstruction::eContextImmediate;
6149 context.SetNoArgs();
6151 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6152 return false;
6154 return true;
6157 // Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and
6158 // the complement of an immediate value, and writes the result to the
6159 // destination register. It can optionally update the condition flags based on
6160 // the result.
6161 bool EmulateInstructionARM::EmulateBICImm(const uint32_t opcode,
6162 const ARMEncoding encoding) {
6163 #if 0
6164 // ARM pseudo code...
6165 if ConditionPassed() then
6166 EncodingSpecificOperations();
6167 result = R[n] AND NOT(imm32);
6168 if d == 15 then // Can only occur for ARM encoding
6169 ALUWritePC(result); // setflags is always FALSE here
6170 else
6171 R[d] = result;
6172 if setflags then
6173 APSR.N = result<31>;
6174 APSR.Z = IsZeroBit(result);
6175 APSR.C = carry;
6176 // APSR.V unchanged
6177 #endif
6179 bool success = false;
6181 if (ConditionPassed(opcode)) {
6182 uint32_t Rd, Rn;
6183 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to
6184 // the value obtained from Rn
6185 bool setflags;
6186 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6187 switch (encoding) {
6188 case eEncodingT1:
6189 Rd = Bits32(opcode, 11, 8);
6190 Rn = Bits32(opcode, 19, 16);
6191 setflags = BitIsSet(opcode, 20);
6192 imm32 = ThumbExpandImm_C(
6193 opcode, APSR_C,
6194 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6195 if (BadReg(Rd) || BadReg(Rn))
6196 return false;
6197 break;
6198 case eEncodingA1:
6199 Rd = Bits32(opcode, 15, 12);
6200 Rn = Bits32(opcode, 19, 16);
6201 setflags = BitIsSet(opcode, 20);
6202 imm32 =
6203 ARMExpandImm_C(opcode, APSR_C,
6204 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6206 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
6207 // instructions;
6208 if (Rd == 15 && setflags)
6209 return EmulateSUBSPcLrEtc(opcode, encoding);
6210 break;
6211 default:
6212 return false;
6215 // Read the first operand.
6216 uint32_t val1 = ReadCoreReg(Rn, &success);
6217 if (!success)
6218 return false;
6220 uint32_t result = val1 & ~imm32;
6222 EmulateInstruction::Context context;
6223 context.type = EmulateInstruction::eContextImmediate;
6224 context.SetNoArgs();
6226 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6227 return false;
6229 return true;
6232 // Bitwise Bit Clear (register) performs a bitwise AND of a register value and
6233 // the complement of an optionally-shifted register value, and writes the
6234 // result to the destination register. It can optionally update the condition
6235 // flags based on the result.
6236 bool EmulateInstructionARM::EmulateBICReg(const uint32_t opcode,
6237 const ARMEncoding encoding) {
6238 #if 0
6239 // ARM pseudo code...
6240 if ConditionPassed() then
6241 EncodingSpecificOperations();
6242 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6243 result = R[n] AND NOT(shifted);
6244 if d == 15 then // Can only occur for ARM encoding
6245 ALUWritePC(result); // setflags is always FALSE here
6246 else
6247 R[d] = result;
6248 if setflags then
6249 APSR.N = result<31>;
6250 APSR.Z = IsZeroBit(result);
6251 APSR.C = carry;
6252 // APSR.V unchanged
6253 #endif
6255 bool success = false;
6257 if (ConditionPassed(opcode)) {
6258 uint32_t Rd, Rn, Rm;
6259 ARM_ShifterType shift_t;
6260 uint32_t shift_n; // the shift applied to the value read from Rm
6261 bool setflags;
6262 uint32_t carry;
6263 switch (encoding) {
6264 case eEncodingT1:
6265 Rd = Rn = Bits32(opcode, 2, 0);
6266 Rm = Bits32(opcode, 5, 3);
6267 setflags = !InITBlock();
6268 shift_t = SRType_LSL;
6269 shift_n = 0;
6270 break;
6271 case eEncodingT2:
6272 Rd = Bits32(opcode, 11, 8);
6273 Rn = Bits32(opcode, 19, 16);
6274 Rm = Bits32(opcode, 3, 0);
6275 setflags = BitIsSet(opcode, 20);
6276 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6277 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
6278 return false;
6279 break;
6280 case eEncodingA1:
6281 Rd = Bits32(opcode, 15, 12);
6282 Rn = Bits32(opcode, 19, 16);
6283 Rm = Bits32(opcode, 3, 0);
6284 setflags = BitIsSet(opcode, 20);
6285 shift_n = DecodeImmShiftARM(opcode, shift_t);
6287 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
6288 // instructions;
6289 if (Rd == 15 && setflags)
6290 return EmulateSUBSPcLrEtc(opcode, encoding);
6291 break;
6292 default:
6293 return false;
6296 // Read the first operand.
6297 uint32_t val1 = ReadCoreReg(Rn, &success);
6298 if (!success)
6299 return false;
6301 // Read the second operand.
6302 uint32_t val2 = ReadCoreReg(Rm, &success);
6303 if (!success)
6304 return false;
6306 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
6307 if (!success)
6308 return false;
6309 uint32_t result = val1 & ~shifted;
6311 EmulateInstruction::Context context;
6312 context.type = EmulateInstruction::eContextImmediate;
6313 context.SetNoArgs();
6315 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6316 return false;
6318 return true;
6321 // LDR (immediate, ARM) calculates an address from a base register value and an
6322 // immediate offset, loads a word
6323 // from memory, and writes it to a register. It can use offset, post-indexed,
6324 // or pre-indexed addressing.
6325 bool EmulateInstructionARM::EmulateLDRImmediateARM(const uint32_t opcode,
6326 const ARMEncoding encoding) {
6327 #if 0
6328 if ConditionPassed() then
6329 EncodingSpecificOperations();
6330 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6331 address = if index then offset_addr else R[n];
6332 data = MemU[address,4];
6333 if wback then R[n] = offset_addr;
6334 if t == 15 then
6335 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6336 elsif UnalignedSupport() || address<1:0> = '00' then
6337 R[t] = data;
6338 else // Can only apply before ARMv7
6339 R[t] = ROR(data, 8*UInt(address<1:0>));
6340 #endif
6342 bool success = false;
6344 if (ConditionPassed(opcode)) {
6345 const uint32_t addr_byte_size = GetAddressByteSize();
6347 uint32_t t;
6348 uint32_t n;
6349 uint32_t imm32;
6350 bool index;
6351 bool add;
6352 bool wback;
6354 switch (encoding) {
6355 case eEncodingA1:
6356 // if Rn == '1111' then SEE LDR (literal);
6357 // if P == '0' && W == '1' then SEE LDRT;
6358 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 ==
6359 // '000000000100' then SEE POP;
6360 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6361 t = Bits32(opcode, 15, 12);
6362 n = Bits32(opcode, 19, 16);
6363 imm32 = Bits32(opcode, 11, 0);
6365 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6366 // (W == '1');
6367 index = BitIsSet(opcode, 24);
6368 add = BitIsSet(opcode, 23);
6369 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
6371 // if wback && n == t then UNPREDICTABLE;
6372 if (wback && (n == t))
6373 return false;
6375 break;
6377 default:
6378 return false;
6381 addr_t address;
6382 addr_t offset_addr;
6383 addr_t base_address = ReadCoreReg(n, &success);
6384 if (!success)
6385 return false;
6387 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6388 if (add)
6389 offset_addr = base_address + imm32;
6390 else
6391 offset_addr = base_address - imm32;
6393 // address = if index then offset_addr else R[n];
6394 if (index)
6395 address = offset_addr;
6396 else
6397 address = base_address;
6399 // data = MemU[address,4];
6401 std::optional<RegisterInfo> base_reg =
6402 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
6403 EmulateInstruction::Context context;
6404 context.type = eContextRegisterLoad;
6405 context.SetRegisterPlusOffset(*base_reg, address - base_address);
6407 uint64_t data = MemURead(context, address, addr_byte_size, 0, &success);
6408 if (!success)
6409 return false;
6411 // if wback then R[n] = offset_addr;
6412 if (wback) {
6413 context.type = eContextAdjustBaseRegister;
6414 context.SetAddress(offset_addr);
6415 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6416 offset_addr))
6417 return false;
6420 // if t == 15 then
6421 if (t == 15) {
6422 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6423 if (BitIsClear(address, 1) && BitIsClear(address, 0)) {
6424 // LoadWritePC (data);
6425 context.type = eContextRegisterLoad;
6426 context.SetRegisterPlusOffset(*base_reg, address - base_address);
6427 LoadWritePC(context, data);
6428 } else
6429 return false;
6431 // elsif UnalignedSupport() || address<1:0> = '00' then
6432 else if (UnalignedSupport() ||
6433 (BitIsClear(address, 1) && BitIsClear(address, 0))) {
6434 // R[t] = data;
6435 context.type = eContextRegisterLoad;
6436 context.SetRegisterPlusOffset(*base_reg, address - base_address);
6437 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6438 data))
6439 return false;
6441 // else // Can only apply before ARMv7
6442 else {
6443 // R[t] = ROR(data, 8*UInt(address<1:0>));
6444 data = ROR(data, Bits32(address, 1, 0), &success);
6445 if (!success)
6446 return false;
6447 context.type = eContextRegisterLoad;
6448 context.SetImmediate(data);
6449 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6450 data))
6451 return false;
6454 return true;
6457 // LDR (register) calculates an address from a base register value and an offset
6458 // register value, loads a word
6459 // from memory, and writes it to a register. The offset register value can
6460 // optionally be shifted.
6461 bool EmulateInstructionARM::EmulateLDRRegister(const uint32_t opcode,
6462 const ARMEncoding encoding) {
6463 #if 0
6464 if ConditionPassed() then
6465 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6466 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6467 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6468 address = if index then offset_addr else R[n];
6469 data = MemU[address,4];
6470 if wback then R[n] = offset_addr;
6471 if t == 15 then
6472 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6473 elsif UnalignedSupport() || address<1:0> = '00' then
6474 R[t] = data;
6475 else // Can only apply before ARMv7
6476 if CurrentInstrSet() == InstrSet_ARM then
6477 R[t] = ROR(data, 8*UInt(address<1:0>));
6478 else
6479 R[t] = bits(32) UNKNOWN;
6480 #endif
6482 bool success = false;
6484 if (ConditionPassed(opcode)) {
6485 const uint32_t addr_byte_size = GetAddressByteSize();
6487 uint32_t t;
6488 uint32_t n;
6489 uint32_t m;
6490 bool index;
6491 bool add;
6492 bool wback;
6493 ARM_ShifterType shift_t;
6494 uint32_t shift_n;
6496 switch (encoding) {
6497 case eEncodingT1:
6498 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
6499 // in ThumbEE";
6500 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6501 t = Bits32(opcode, 2, 0);
6502 n = Bits32(opcode, 5, 3);
6503 m = Bits32(opcode, 8, 6);
6505 // index = TRUE; add = TRUE; wback = FALSE;
6506 index = true;
6507 add = true;
6508 wback = false;
6510 // (shift_t, shift_n) = (SRType_LSL, 0);
6511 shift_t = SRType_LSL;
6512 shift_n = 0;
6514 break;
6516 case eEncodingT2:
6517 // if Rn == '1111' then SEE LDR (literal);
6518 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6519 t = Bits32(opcode, 15, 12);
6520 n = Bits32(opcode, 19, 16);
6521 m = Bits32(opcode, 3, 0);
6523 // index = TRUE; add = TRUE; wback = FALSE;
6524 index = true;
6525 add = true;
6526 wback = false;
6528 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6529 shift_t = SRType_LSL;
6530 shift_n = Bits32(opcode, 5, 4);
6532 // if BadReg(m) then UNPREDICTABLE;
6533 if (BadReg(m))
6534 return false;
6536 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
6537 if ((t == 15) && InITBlock() && !LastInITBlock())
6538 return false;
6540 break;
6542 case eEncodingA1: {
6543 // if P == '0' && W == '1' then SEE LDRT;
6544 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6545 t = Bits32(opcode, 15, 12);
6546 n = Bits32(opcode, 19, 16);
6547 m = Bits32(opcode, 3, 0);
6549 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6550 // (W == '1');
6551 index = BitIsSet(opcode, 24);
6552 add = BitIsSet(opcode, 23);
6553 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
6555 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6556 uint32_t type = Bits32(opcode, 6, 5);
6557 uint32_t imm5 = Bits32(opcode, 11, 7);
6558 shift_n = DecodeImmShift(type, imm5, shift_t);
6560 // if m == 15 then UNPREDICTABLE;
6561 if (m == 15)
6562 return false;
6564 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6565 if (wback && ((n == 15) || (n == t)))
6566 return false;
6567 } break;
6569 default:
6570 return false;
6573 uint32_t Rm =
6574 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6575 if (!success)
6576 return false;
6578 uint32_t Rn =
6579 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6580 if (!success)
6581 return false;
6583 addr_t offset_addr;
6584 addr_t address;
6586 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is
6587 // an application level alias for the CPSR".
6588 addr_t offset =
6589 Shift(Rm, shift_t, shift_n, Bit32(m_opcode_cpsr, APSR_C), &success);
6590 if (!success)
6591 return false;
6593 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6594 if (add)
6595 offset_addr = Rn + offset;
6596 else
6597 offset_addr = Rn - offset;
6599 // address = if index then offset_addr else R[n];
6600 if (index)
6601 address = offset_addr;
6602 else
6603 address = Rn;
6605 // data = MemU[address,4];
6606 std::optional<RegisterInfo> base_reg =
6607 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
6608 EmulateInstruction::Context context;
6609 context.type = eContextRegisterLoad;
6610 context.SetRegisterPlusOffset(*base_reg, address - Rn);
6612 uint64_t data = MemURead(context, address, addr_byte_size, 0, &success);
6613 if (!success)
6614 return false;
6616 // if wback then R[n] = offset_addr;
6617 if (wback) {
6618 context.type = eContextAdjustBaseRegister;
6619 context.SetAddress(offset_addr);
6620 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6621 offset_addr))
6622 return false;
6625 // if t == 15 then
6626 if (t == 15) {
6627 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6628 if (BitIsClear(address, 1) && BitIsClear(address, 0)) {
6629 context.type = eContextRegisterLoad;
6630 context.SetRegisterPlusOffset(*base_reg, address - Rn);
6631 LoadWritePC(context, data);
6632 } else
6633 return false;
6635 // elsif UnalignedSupport() || address<1:0> = '00' then
6636 else if (UnalignedSupport() ||
6637 (BitIsClear(address, 1) && BitIsClear(address, 0))) {
6638 // R[t] = data;
6639 context.type = eContextRegisterLoad;
6640 context.SetRegisterPlusOffset(*base_reg, address - Rn);
6641 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6642 data))
6643 return false;
6644 } else // Can only apply before ARMv7
6646 // if CurrentInstrSet() == InstrSet_ARM then
6647 if (CurrentInstrSet() == eModeARM) {
6648 // R[t] = ROR(data, 8*UInt(address<1:0>));
6649 data = ROR(data, Bits32(address, 1, 0), &success);
6650 if (!success)
6651 return false;
6652 context.type = eContextRegisterLoad;
6653 context.SetImmediate(data);
6654 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6655 data))
6656 return false;
6657 } else {
6658 // R[t] = bits(32) UNKNOWN;
6659 WriteBits32Unknown(t);
6663 return true;
6666 // LDRB (immediate, Thumb)
6667 bool EmulateInstructionARM::EmulateLDRBImmediate(const uint32_t opcode,
6668 const ARMEncoding encoding) {
6669 #if 0
6670 if ConditionPassed() then
6671 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6672 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6673 address = if index then offset_addr else R[n];
6674 R[t] = ZeroExtend(MemU[address,1], 32);
6675 if wback then R[n] = offset_addr;
6676 #endif
6678 bool success = false;
6680 if (ConditionPassed(opcode)) {
6681 uint32_t t;
6682 uint32_t n;
6683 uint32_t imm32;
6684 bool index;
6685 bool add;
6686 bool wback;
6688 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6689 switch (encoding) {
6690 case eEncodingT1:
6691 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6692 t = Bits32(opcode, 2, 0);
6693 n = Bits32(opcode, 5, 3);
6694 imm32 = Bits32(opcode, 10, 6);
6696 // index = TRUE; add = TRUE; wback = FALSE;
6697 index = true;
6698 add = true;
6699 wback = false;
6701 break;
6703 case eEncodingT2:
6704 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6705 t = Bits32(opcode, 15, 12);
6706 n = Bits32(opcode, 19, 16);
6707 imm32 = Bits32(opcode, 11, 0);
6709 // index = TRUE; add = TRUE; wback = FALSE;
6710 index = true;
6711 add = true;
6712 wback = false;
6714 // if Rt == '1111' then SEE PLD;
6715 if (t == 15)
6716 return false; // PLD is not implemented yet
6718 // if Rn == '1111' then SEE LDRB (literal);
6719 if (n == 15)
6720 return EmulateLDRBLiteral(opcode, eEncodingT1);
6722 // if t == 13 then UNPREDICTABLE;
6723 if (t == 13)
6724 return false;
6726 break;
6728 case eEncodingT3:
6729 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
6730 // if P == '0' && W == '0' then UNDEFINED;
6731 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
6732 return false;
6734 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6735 t = Bits32(opcode, 15, 12);
6736 n = Bits32(opcode, 19, 16);
6737 imm32 = Bits32(opcode, 7, 0);
6739 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
6740 index = BitIsSet(opcode, 10);
6741 add = BitIsSet(opcode, 9);
6742 wback = BitIsSet(opcode, 8);
6744 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
6745 if (t == 15)
6746 return false; // PLD is not implemented yet
6748 // if Rn == '1111' then SEE LDRB (literal);
6749 if (n == 15)
6750 return EmulateLDRBLiteral(opcode, eEncodingT1);
6752 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6753 if (BadReg(t) || (wback && (n == t)))
6754 return false;
6756 break;
6758 default:
6759 return false;
6762 uint32_t Rn =
6763 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6764 if (!success)
6765 return false;
6767 addr_t address;
6768 addr_t offset_addr;
6770 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6771 if (add)
6772 offset_addr = Rn + imm32;
6773 else
6774 offset_addr = Rn - imm32;
6776 // address = if index then offset_addr else R[n];
6777 if (index)
6778 address = offset_addr;
6779 else
6780 address = Rn;
6782 // R[t] = ZeroExtend(MemU[address,1], 32);
6783 std::optional<RegisterInfo> base_reg =
6784 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
6785 std::optional<RegisterInfo> data_reg =
6786 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
6788 EmulateInstruction::Context context;
6789 context.type = eContextRegisterLoad;
6790 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);
6792 uint64_t data = MemURead(context, address, 1, 0, &success);
6793 if (!success)
6794 return false;
6796 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
6797 return false;
6799 // if wback then R[n] = offset_addr;
6800 if (wback) {
6801 context.type = eContextAdjustBaseRegister;
6802 context.SetAddress(offset_addr);
6803 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6804 offset_addr))
6805 return false;
6808 return true;
6811 // LDRB (literal) calculates an address from the PC value and an immediate
6812 // offset, loads a byte from memory,
6813 // zero-extends it to form a 32-bit word and writes it to a register.
6814 bool EmulateInstructionARM::EmulateLDRBLiteral(const uint32_t opcode,
6815 const ARMEncoding encoding) {
6816 #if 0
6817 if ConditionPassed() then
6818 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6819 base = Align(PC,4);
6820 address = if add then (base + imm32) else (base - imm32);
6821 R[t] = ZeroExtend(MemU[address,1], 32);
6822 #endif
6824 bool success = false;
6826 if (ConditionPassed(opcode)) {
6827 uint32_t t;
6828 uint32_t imm32;
6829 bool add;
6830 switch (encoding) {
6831 case eEncodingT1:
6832 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6833 t = Bits32(opcode, 15, 12);
6834 imm32 = Bits32(opcode, 11, 0);
6835 add = BitIsSet(opcode, 23);
6837 // if Rt == '1111' then SEE PLD;
6838 if (t == 15)
6839 return false; // PLD is not implemented yet
6841 // if t == 13 then UNPREDICTABLE;
6842 if (t == 13)
6843 return false;
6845 break;
6847 case eEncodingA1:
6848 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6849 t = Bits32(opcode, 15, 12);
6850 imm32 = Bits32(opcode, 11, 0);
6851 add = BitIsSet(opcode, 23);
6853 // if t == 15 then UNPREDICTABLE;
6854 if (t == 15)
6855 return false;
6856 break;
6858 default:
6859 return false;
6862 // base = Align(PC,4);
6863 uint32_t pc_val = ReadCoreReg(PC_REG, &success);
6864 if (!success)
6865 return false;
6867 uint32_t base = AlignPC(pc_val);
6869 addr_t address;
6870 // address = if add then (base + imm32) else (base - imm32);
6871 if (add)
6872 address = base + imm32;
6873 else
6874 address = base - imm32;
6876 // R[t] = ZeroExtend(MemU[address,1], 32);
6877 EmulateInstruction::Context context;
6878 context.type = eContextRelativeBranchImmediate;
6879 context.SetImmediate(address - base);
6881 uint64_t data = MemURead(context, address, 1, 0, &success);
6882 if (!success)
6883 return false;
6885 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
6886 return false;
6888 return true;
6891 // LDRB (register) calculates an address from a base register value and an
6892 // offset rigister value, loads a byte from memory, zero-extends it to form a
6893 // 32-bit word, and writes it to a register. The offset register value can
6894 // optionally be shifted.
6895 bool EmulateInstructionARM::EmulateLDRBRegister(const uint32_t opcode,
6896 const ARMEncoding encoding) {
6897 #if 0
6898 if ConditionPassed() then
6899 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6900 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6901 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6902 address = if index then offset_addr else R[n];
6903 R[t] = ZeroExtend(MemU[address,1],32);
6904 if wback then R[n] = offset_addr;
6905 #endif
6907 bool success = false;
6909 if (ConditionPassed(opcode)) {
6910 uint32_t t;
6911 uint32_t n;
6912 uint32_t m;
6913 bool index;
6914 bool add;
6915 bool wback;
6916 ARM_ShifterType shift_t;
6917 uint32_t shift_n;
6919 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6920 switch (encoding) {
6921 case eEncodingT1:
6922 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6923 t = Bits32(opcode, 2, 0);
6924 n = Bits32(opcode, 5, 3);
6925 m = Bits32(opcode, 8, 6);
6927 // index = TRUE; add = TRUE; wback = FALSE;
6928 index = true;
6929 add = true;
6930 wback = false;
6932 // (shift_t, shift_n) = (SRType_LSL, 0);
6933 shift_t = SRType_LSL;
6934 shift_n = 0;
6935 break;
6937 case eEncodingT2:
6938 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6939 t = Bits32(opcode, 15, 12);
6940 n = Bits32(opcode, 19, 16);
6941 m = Bits32(opcode, 3, 0);
6943 // index = TRUE; add = TRUE; wback = FALSE;
6944 index = true;
6945 add = true;
6946 wback = false;
6948 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6949 shift_t = SRType_LSL;
6950 shift_n = Bits32(opcode, 5, 4);
6952 // if Rt == '1111' then SEE PLD;
6953 if (t == 15)
6954 return false; // PLD is not implemented yet
6956 // if Rn == '1111' then SEE LDRB (literal);
6957 if (n == 15)
6958 return EmulateLDRBLiteral(opcode, eEncodingT1);
6960 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6961 if ((t == 13) || BadReg(m))
6962 return false;
6963 break;
6965 case eEncodingA1: {
6966 // if P == '0' && W == '1' then SEE LDRBT;
6967 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6968 t = Bits32(opcode, 15, 12);
6969 n = Bits32(opcode, 19, 16);
6970 m = Bits32(opcode, 3, 0);
6972 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6973 // (W == '1');
6974 index = BitIsSet(opcode, 24);
6975 add = BitIsSet(opcode, 23);
6976 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
6978 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6979 uint32_t type = Bits32(opcode, 6, 5);
6980 uint32_t imm5 = Bits32(opcode, 11, 7);
6981 shift_n = DecodeImmShift(type, imm5, shift_t);
6983 // if t == 15 || m == 15 then UNPREDICTABLE;
6984 if ((t == 15) || (m == 15))
6985 return false;
6987 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6988 if (wback && ((n == 15) || (n == t)))
6989 return false;
6990 } break;
6992 default:
6993 return false;
6996 addr_t offset_addr;
6997 addr_t address;
6999 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7000 uint32_t Rm =
7001 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7002 if (!success)
7003 return false;
7005 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
7006 if (!success)
7007 return false;
7009 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7010 uint32_t Rn =
7011 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7012 if (!success)
7013 return false;
7015 if (add)
7016 offset_addr = Rn + offset;
7017 else
7018 offset_addr = Rn - offset;
7020 // address = if index then offset_addr else R[n];
7021 if (index)
7022 address = offset_addr;
7023 else
7024 address = Rn;
7026 // R[t] = ZeroExtend(MemU[address,1],32);
7027 std::optional<RegisterInfo> base_reg =
7028 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
7030 EmulateInstruction::Context context;
7031 context.type = eContextRegisterLoad;
7032 context.SetRegisterPlusOffset(*base_reg, address - Rn);
7034 uint64_t data = MemURead(context, address, 1, 0, &success);
7035 if (!success)
7036 return false;
7038 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
7039 return false;
7041 // if wback then R[n] = offset_addr;
7042 if (wback) {
7043 context.type = eContextAdjustBaseRegister;
7044 context.SetAddress(offset_addr);
7045 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7046 offset_addr))
7047 return false;
7050 return true;
7053 // LDRH (immediate, Thumb) calculates an address from a base register value and
7054 // an immediate offset, loads a
7055 // halfword from memory, zero-extends it to form a 32-bit word, and writes it
7056 // to a register. It can use offset, post-indexed, or pre-indexed addressing.
7057 bool EmulateInstructionARM::EmulateLDRHImmediate(const uint32_t opcode,
7058 const ARMEncoding encoding) {
7059 #if 0
7060 if ConditionPassed() then
7061 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7062 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7063 address = if index then offset_addr else R[n];
7064 data = MemU[address,2];
7065 if wback then R[n] = offset_addr;
7066 if UnalignedSupport() || address<0> = '0' then
7067 R[t] = ZeroExtend(data, 32);
7068 else // Can only apply before ARMv7
7069 R[t] = bits(32) UNKNOWN;
7070 #endif
7072 bool success = false;
7074 if (ConditionPassed(opcode)) {
7075 uint32_t t;
7076 uint32_t n;
7077 uint32_t imm32;
7078 bool index;
7079 bool add;
7080 bool wback;
7082 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7083 switch (encoding) {
7084 case eEncodingT1:
7085 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
7086 t = Bits32(opcode, 2, 0);
7087 n = Bits32(opcode, 5, 3);
7088 imm32 = Bits32(opcode, 10, 6) << 1;
7090 // index = TRUE; add = TRUE; wback = FALSE;
7091 index = true;
7092 add = true;
7093 wback = false;
7095 break;
7097 case eEncodingT2:
7098 // if Rt == '1111' then SEE "Unallocated memory hints";
7099 // if Rn == '1111' then SEE LDRH (literal);
7100 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7101 t = Bits32(opcode, 15, 12);
7102 n = Bits32(opcode, 19, 16);
7103 imm32 = Bits32(opcode, 11, 0);
7105 // index = TRUE; add = TRUE; wback = FALSE;
7106 index = true;
7107 add = true;
7108 wback = false;
7110 // if t == 13 then UNPREDICTABLE;
7111 if (t == 13)
7112 return false;
7113 break;
7115 case eEncodingT3:
7116 // if Rn == '1111' then SEE LDRH (literal);
7117 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE
7118 // "Unallocated memory hints";
7119 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
7120 // if P == '0' && W == '0' then UNDEFINED;
7121 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
7122 return false;
7124 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7125 t = Bits32(opcode, 15, 12);
7126 n = Bits32(opcode, 19, 16);
7127 imm32 = Bits32(opcode, 7, 0);
7129 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7130 index = BitIsSet(opcode, 10);
7131 add = BitIsSet(opcode, 9);
7132 wback = BitIsSet(opcode, 8);
7134 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7135 if (BadReg(t) || (wback && (n == t)))
7136 return false;
7137 break;
7139 default:
7140 return false;
7143 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7144 uint32_t Rn =
7145 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7146 if (!success)
7147 return false;
7149 addr_t offset_addr;
7150 addr_t address;
7152 if (add)
7153 offset_addr = Rn + imm32;
7154 else
7155 offset_addr = Rn - imm32;
7157 // address = if index then offset_addr else R[n];
7158 if (index)
7159 address = offset_addr;
7160 else
7161 address = Rn;
7163 // data = MemU[address,2];
7164 std::optional<RegisterInfo> base_reg =
7165 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
7167 EmulateInstruction::Context context;
7168 context.type = eContextRegisterLoad;
7169 context.SetRegisterPlusOffset(*base_reg, address - Rn);
7171 uint64_t data = MemURead(context, address, 2, 0, &success);
7172 if (!success)
7173 return false;
7175 // if wback then R[n] = offset_addr;
7176 if (wback) {
7177 context.type = eContextAdjustBaseRegister;
7178 context.SetAddress(offset_addr);
7179 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7180 offset_addr))
7181 return false;
7184 // if UnalignedSupport() || address<0> = '0' then
7185 if (UnalignedSupport() || BitIsClear(address, 0)) {
7186 // R[t] = ZeroExtend(data, 32);
7187 context.type = eContextRegisterLoad;
7188 context.SetRegisterPlusOffset(*base_reg, address - Rn);
7189 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7190 data))
7191 return false;
7192 } else // Can only apply before ARMv7
7194 // R[t] = bits(32) UNKNOWN;
7195 WriteBits32Unknown(t);
7198 return true;
7201 // LDRH (literal) calculates an address from the PC value and an immediate
7202 // offset, loads a halfword from memory,
7203 // zero-extends it to form a 32-bit word, and writes it to a register.
7204 bool EmulateInstructionARM::EmulateLDRHLiteral(const uint32_t opcode,
7205 const ARMEncoding encoding) {
7206 #if 0
7207 if ConditionPassed() then
7208 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7209 base = Align(PC,4);
7210 address = if add then (base + imm32) else (base - imm32);
7211 data = MemU[address,2];
7212 if UnalignedSupport() || address<0> = '0' then
7213 R[t] = ZeroExtend(data, 32);
7214 else // Can only apply before ARMv7
7215 R[t] = bits(32) UNKNOWN;
7216 #endif
7218 bool success = false;
7220 if (ConditionPassed(opcode)) {
7221 uint32_t t;
7222 uint32_t imm32;
7223 bool add;
7225 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7226 switch (encoding) {
7227 case eEncodingT1:
7228 // if Rt == '1111' then SEE "Unallocated memory hints";
7229 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
7230 t = Bits32(opcode, 15, 12);
7231 imm32 = Bits32(opcode, 11, 0);
7232 add = BitIsSet(opcode, 23);
7234 // if t == 13 then UNPREDICTABLE;
7235 if (t == 13)
7236 return false;
7238 break;
7240 case eEncodingA1: {
7241 uint32_t imm4H = Bits32(opcode, 11, 8);
7242 uint32_t imm4L = Bits32(opcode, 3, 0);
7244 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7245 t = Bits32(opcode, 15, 12);
7246 imm32 = (imm4H << 4) | imm4L;
7247 add = BitIsSet(opcode, 23);
7249 // if t == 15 then UNPREDICTABLE;
7250 if (t == 15)
7251 return false;
7252 break;
7255 default:
7256 return false;
7259 // base = Align(PC,4);
7260 uint64_t pc_value = ReadCoreReg(PC_REG, &success);
7261 if (!success)
7262 return false;
7264 addr_t base = AlignPC(pc_value);
7265 addr_t address;
7267 // address = if add then (base + imm32) else (base - imm32);
7268 if (add)
7269 address = base + imm32;
7270 else
7271 address = base - imm32;
7273 // data = MemU[address,2];
7274 std::optional<RegisterInfo> base_reg =
7275 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7277 EmulateInstruction::Context context;
7278 context.type = eContextRegisterLoad;
7279 context.SetRegisterPlusOffset(*base_reg, address - base);
7281 uint64_t data = MemURead(context, address, 2, 0, &success);
7282 if (!success)
7283 return false;
7285 // if UnalignedSupport() || address<0> = '0' then
7286 if (UnalignedSupport() || BitIsClear(address, 0)) {
7287 // R[t] = ZeroExtend(data, 32);
7288 context.type = eContextRegisterLoad;
7289 context.SetRegisterPlusOffset(*base_reg, address - base);
7290 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7291 data))
7292 return false;
7294 } else // Can only apply before ARMv7
7296 // R[t] = bits(32) UNKNOWN;
7297 WriteBits32Unknown(t);
7300 return true;
7303 // LDRH (literal) calculates an address from a base register value and an offset
7304 // register value, loads a halfword
7305 // from memory, zero-extends it to form a 32-bit word, and writes it to a
7306 // register. The offset register value can be shifted left by 0, 1, 2, or 3
7307 // bits.
7308 bool EmulateInstructionARM::EmulateLDRHRegister(const uint32_t opcode,
7309 const ARMEncoding encoding) {
7310 #if 0
7311 if ConditionPassed() then
7312 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7313 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7314 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7315 address = if index then offset_addr else R[n];
7316 data = MemU[address,2];
7317 if wback then R[n] = offset_addr;
7318 if UnalignedSupport() || address<0> = '0' then
7319 R[t] = ZeroExtend(data, 32);
7320 else // Can only apply before ARMv7
7321 R[t] = bits(32) UNKNOWN;
7322 #endif
7324 bool success = false;
7326 if (ConditionPassed(opcode)) {
7327 uint32_t t;
7328 uint32_t n;
7329 uint32_t m;
7330 bool index;
7331 bool add;
7332 bool wback;
7333 ARM_ShifterType shift_t;
7334 uint32_t shift_n;
7336 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7337 switch (encoding) {
7338 case eEncodingT1:
7339 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
7340 // in ThumbEE";
7341 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7342 t = Bits32(opcode, 2, 0);
7343 n = Bits32(opcode, 5, 3);
7344 m = Bits32(opcode, 8, 6);
7346 // index = TRUE; add = TRUE; wback = FALSE;
7347 index = true;
7348 add = true;
7349 wback = false;
7351 // (shift_t, shift_n) = (SRType_LSL, 0);
7352 shift_t = SRType_LSL;
7353 shift_n = 0;
7355 break;
7357 case eEncodingT2:
7358 // if Rn == '1111' then SEE LDRH (literal);
7359 // if Rt == '1111' then SEE "Unallocated memory hints";
7360 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7361 t = Bits32(opcode, 15, 12);
7362 n = Bits32(opcode, 19, 16);
7363 m = Bits32(opcode, 3, 0);
7365 // index = TRUE; add = TRUE; wback = FALSE;
7366 index = true;
7367 add = true;
7368 wback = false;
7370 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7371 shift_t = SRType_LSL;
7372 shift_n = Bits32(opcode, 5, 4);
7374 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7375 if ((t == 13) || BadReg(m))
7376 return false;
7377 break;
7379 case eEncodingA1:
7380 // if P == '0' && W == '1' then SEE LDRHT;
7381 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7382 t = Bits32(opcode, 15, 12);
7383 n = Bits32(opcode, 19, 16);
7384 m = Bits32(opcode, 3, 0);
7386 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7387 // (W == '1');
7388 index = BitIsSet(opcode, 24);
7389 add = BitIsSet(opcode, 23);
7390 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
7392 // (shift_t, shift_n) = (SRType_LSL, 0);
7393 shift_t = SRType_LSL;
7394 shift_n = 0;
7396 // if t == 15 || m == 15 then UNPREDICTABLE;
7397 if ((t == 15) || (m == 15))
7398 return false;
7400 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7401 if (wback && ((n == 15) || (n == t)))
7402 return false;
7404 break;
7406 default:
7407 return false;
7410 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7412 uint64_t Rm =
7413 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7414 if (!success)
7415 return false;
7417 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
7418 if (!success)
7419 return false;
7421 addr_t offset_addr;
7422 addr_t address;
7424 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7425 uint64_t Rn =
7426 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7427 if (!success)
7428 return false;
7430 if (add)
7431 offset_addr = Rn + offset;
7432 else
7433 offset_addr = Rn - offset;
7435 // address = if index then offset_addr else R[n];
7436 if (index)
7437 address = offset_addr;
7438 else
7439 address = Rn;
7441 // data = MemU[address,2];
7442 std::optional<RegisterInfo> base_reg =
7443 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
7444 std::optional<RegisterInfo> offset_reg =
7445 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
7447 EmulateInstruction::Context context;
7448 context.type = eContextRegisterLoad;
7449 context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg);
7450 uint64_t data = MemURead(context, address, 2, 0, &success);
7451 if (!success)
7452 return false;
7454 // if wback then R[n] = offset_addr;
7455 if (wback) {
7456 context.type = eContextAdjustBaseRegister;
7457 context.SetAddress(offset_addr);
7458 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7459 offset_addr))
7460 return false;
7463 // if UnalignedSupport() || address<0> = '0' then
7464 if (UnalignedSupport() || BitIsClear(address, 0)) {
7465 // R[t] = ZeroExtend(data, 32);
7466 context.type = eContextRegisterLoad;
7467 context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg);
7468 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7469 data))
7470 return false;
7471 } else // Can only apply before ARMv7
7473 // R[t] = bits(32) UNKNOWN;
7474 WriteBits32Unknown(t);
7477 return true;
7480 // LDRSB (immediate) calculates an address from a base register value and an
7481 // immediate offset, loads a byte from
7482 // memory, sign-extends it to form a 32-bit word, and writes it to a register.
7483 // It can use offset, post-indexed, or pre-indexed addressing.
7484 bool EmulateInstructionARM::EmulateLDRSBImmediate(const uint32_t opcode,
7485 const ARMEncoding encoding) {
7486 #if 0
7487 if ConditionPassed() then
7488 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7489 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7490 address = if index then offset_addr else R[n];
7491 R[t] = SignExtend(MemU[address,1], 32);
7492 if wback then R[n] = offset_addr;
7493 #endif
7495 bool success = false;
7497 if (ConditionPassed(opcode)) {
7498 uint32_t t;
7499 uint32_t n;
7500 uint32_t imm32;
7501 bool index;
7502 bool add;
7503 bool wback;
7505 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7506 switch (encoding) {
7507 case eEncodingT1:
7508 // if Rt == '1111' then SEE PLI;
7509 // if Rn == '1111' then SEE LDRSB (literal);
7510 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7511 t = Bits32(opcode, 15, 12);
7512 n = Bits32(opcode, 19, 16);
7513 imm32 = Bits32(opcode, 11, 0);
7515 // index = TRUE; add = TRUE; wback = FALSE;
7516 index = true;
7517 add = true;
7518 wback = false;
7520 // if t == 13 then UNPREDICTABLE;
7521 if (t == 13)
7522 return false;
7524 break;
7526 case eEncodingT2:
7527 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
7528 // if Rn == '1111' then SEE LDRSB (literal);
7529 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
7530 // if P == '0' && W == '0' then UNDEFINED;
7531 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
7532 return false;
7534 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7535 t = Bits32(opcode, 15, 12);
7536 n = Bits32(opcode, 19, 16);
7537 imm32 = Bits32(opcode, 7, 0);
7539 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7540 index = BitIsSet(opcode, 10);
7541 add = BitIsSet(opcode, 9);
7542 wback = BitIsSet(opcode, 8);
7544 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7545 if (((t == 13) ||
7546 ((t == 15) && (BitIsClear(opcode, 10) || BitIsSet(opcode, 9) ||
7547 BitIsSet(opcode, 8)))) ||
7548 (wback && (n == t)))
7549 return false;
7551 break;
7553 case eEncodingA1: {
7554 // if Rn == '1111' then SEE LDRSB (literal);
7555 // if P == '0' && W == '1' then SEE LDRSBT;
7556 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7557 t = Bits32(opcode, 15, 12);
7558 n = Bits32(opcode, 19, 16);
7560 uint32_t imm4H = Bits32(opcode, 11, 8);
7561 uint32_t imm4L = Bits32(opcode, 3, 0);
7562 imm32 = (imm4H << 4) | imm4L;
7564 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7565 // (W == '1');
7566 index = BitIsSet(opcode, 24);
7567 add = BitIsSet(opcode, 23);
7568 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
7570 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7571 if ((t == 15) || (wback && (n == t)))
7572 return false;
7574 break;
7577 default:
7578 return false;
7581 uint64_t Rn = ReadCoreReg(n, &success);
7582 if (!success)
7583 return false;
7585 addr_t offset_addr;
7586 addr_t address;
7588 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7589 if (add)
7590 offset_addr = Rn + imm32;
7591 else
7592 offset_addr = Rn - imm32;
7594 // address = if index then offset_addr else R[n];
7595 if (index)
7596 address = offset_addr;
7597 else
7598 address = Rn;
7600 // R[t] = SignExtend(MemU[address,1], 32);
7601 std::optional<RegisterInfo> base_reg =
7602 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
7604 EmulateInstruction::Context context;
7605 context.type = eContextRegisterLoad;
7606 context.SetRegisterPlusOffset(*base_reg, address - Rn);
7608 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);
7609 if (!success)
7610 return false;
7612 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7613 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7614 (uint64_t)signed_data))
7615 return false;
7617 // if wback then R[n] = offset_addr;
7618 if (wback) {
7619 context.type = eContextAdjustBaseRegister;
7620 context.SetAddress(offset_addr);
7621 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7622 offset_addr))
7623 return false;
7627 return true;
7630 // LDRSB (literal) calculates an address from the PC value and an immediate
7631 // offset, loads a byte from memory,
7632 // sign-extends it to form a 32-bit word, and writes tit to a register.
7633 bool EmulateInstructionARM::EmulateLDRSBLiteral(const uint32_t opcode,
7634 const ARMEncoding encoding) {
7635 #if 0
7636 if ConditionPassed() then
7637 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7638 base = Align(PC,4);
7639 address = if add then (base + imm32) else (base - imm32);
7640 R[t] = SignExtend(MemU[address,1], 32);
7641 #endif
7643 bool success = false;
7645 if (ConditionPassed(opcode)) {
7646 uint32_t t;
7647 uint32_t imm32;
7648 bool add;
7650 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7651 switch (encoding) {
7652 case eEncodingT1:
7653 // if Rt == '1111' then SEE PLI;
7654 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
7655 t = Bits32(opcode, 15, 12);
7656 imm32 = Bits32(opcode, 11, 0);
7657 add = BitIsSet(opcode, 23);
7659 // if t == 13 then UNPREDICTABLE;
7660 if (t == 13)
7661 return false;
7663 break;
7665 case eEncodingA1: {
7666 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7667 t = Bits32(opcode, 15, 12);
7668 uint32_t imm4H = Bits32(opcode, 11, 8);
7669 uint32_t imm4L = Bits32(opcode, 3, 0);
7670 imm32 = (imm4H << 4) | imm4L;
7671 add = BitIsSet(opcode, 23);
7673 // if t == 15 then UNPREDICTABLE;
7674 if (t == 15)
7675 return false;
7677 break;
7680 default:
7681 return false;
7684 // base = Align(PC,4);
7685 uint64_t pc_value = ReadCoreReg(PC_REG, &success);
7686 if (!success)
7687 return false;
7688 uint64_t base = AlignPC(pc_value);
7690 // address = if add then (base + imm32) else (base - imm32);
7691 addr_t address;
7692 if (add)
7693 address = base + imm32;
7694 else
7695 address = base - imm32;
7697 // R[t] = SignExtend(MemU[address,1], 32);
7698 std::optional<RegisterInfo> base_reg =
7699 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7701 EmulateInstruction::Context context;
7702 context.type = eContextRegisterLoad;
7703 context.SetRegisterPlusOffset(*base_reg, address - base);
7705 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);
7706 if (!success)
7707 return false;
7709 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7710 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7711 (uint64_t)signed_data))
7712 return false;
7714 return true;
7717 // LDRSB (register) calculates an address from a base register value and an
7718 // offset register value, loadsa byte from
7719 // memory, sign-extends it to form a 32-bit word, and writes it to a register.
7720 // The offset register value can be shifted left by 0, 1, 2, or 3 bits.
7721 bool EmulateInstructionARM::EmulateLDRSBRegister(const uint32_t opcode,
7722 const ARMEncoding encoding) {
7723 #if 0
7724 if ConditionPassed() then
7725 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7726 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7727 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7728 address = if index then offset_addr else R[n];
7729 R[t] = SignExtend(MemU[address,1], 32);
7730 if wback then R[n] = offset_addr;
7731 #endif
7733 bool success = false;
7735 if (ConditionPassed(opcode)) {
7736 uint32_t t;
7737 uint32_t n;
7738 uint32_t m;
7739 bool index;
7740 bool add;
7741 bool wback;
7742 ARM_ShifterType shift_t;
7743 uint32_t shift_n;
7745 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7746 switch (encoding) {
7747 case eEncodingT1:
7748 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7749 t = Bits32(opcode, 2, 0);
7750 n = Bits32(opcode, 5, 3);
7751 m = Bits32(opcode, 8, 6);
7753 // index = TRUE; add = TRUE; wback = FALSE;
7754 index = true;
7755 add = true;
7756 wback = false;
7758 // (shift_t, shift_n) = (SRType_LSL, 0);
7759 shift_t = SRType_LSL;
7760 shift_n = 0;
7762 break;
7764 case eEncodingT2:
7765 // if Rt == '1111' then SEE PLI;
7766 // if Rn == '1111' then SEE LDRSB (literal);
7767 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7768 t = Bits32(opcode, 15, 12);
7769 n = Bits32(opcode, 19, 16);
7770 m = Bits32(opcode, 3, 0);
7772 // index = TRUE; add = TRUE; wback = FALSE;
7773 index = true;
7774 add = true;
7775 wback = false;
7777 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7778 shift_t = SRType_LSL;
7779 shift_n = Bits32(opcode, 5, 4);
7781 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7782 if ((t == 13) || BadReg(m))
7783 return false;
7784 break;
7786 case eEncodingA1:
7787 // if P == '0' && W == '1' then SEE LDRSBT;
7788 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7789 t = Bits32(opcode, 15, 12);
7790 n = Bits32(opcode, 19, 16);
7791 m = Bits32(opcode, 3, 0);
7793 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7794 // (W == '1');
7795 index = BitIsSet(opcode, 24);
7796 add = BitIsSet(opcode, 23);
7797 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
7799 // (shift_t, shift_n) = (SRType_LSL, 0);
7800 shift_t = SRType_LSL;
7801 shift_n = 0;
7803 // if t == 15 || m == 15 then UNPREDICTABLE;
7804 if ((t == 15) || (m == 15))
7805 return false;
7807 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7808 if (wback && ((n == 15) || (n == t)))
7809 return false;
7810 break;
7812 default:
7813 return false;
7816 uint64_t Rm =
7817 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7818 if (!success)
7819 return false;
7821 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7822 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
7823 if (!success)
7824 return false;
7826 addr_t offset_addr;
7827 addr_t address;
7829 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7830 uint64_t Rn =
7831 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7832 if (!success)
7833 return false;
7835 if (add)
7836 offset_addr = Rn + offset;
7837 else
7838 offset_addr = Rn - offset;
7840 // address = if index then offset_addr else R[n];
7841 if (index)
7842 address = offset_addr;
7843 else
7844 address = Rn;
7846 // R[t] = SignExtend(MemU[address,1], 32);
7847 std::optional<RegisterInfo> base_reg =
7848 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
7849 std::optional<RegisterInfo> offset_reg =
7850 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
7852 EmulateInstruction::Context context;
7853 context.type = eContextRegisterLoad;
7854 context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg);
7856 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);
7857 if (!success)
7858 return false;
7860 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7861 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7862 (uint64_t)signed_data))
7863 return false;
7865 // if wback then R[n] = offset_addr;
7866 if (wback) {
7867 context.type = eContextAdjustBaseRegister;
7868 context.SetAddress(offset_addr);
7869 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7870 offset_addr))
7871 return false;
7874 return true;
7877 // LDRSH (immediate) calculates an address from a base register value and an
7878 // immediate offset, loads a halfword from
7879 // memory, sign-extends it to form a 32-bit word, and writes it to a register.
7880 // It can use offset, post-indexed, or pre-indexed addressing.
7881 bool EmulateInstructionARM::EmulateLDRSHImmediate(const uint32_t opcode,
7882 const ARMEncoding encoding) {
7883 #if 0
7884 if ConditionPassed() then
7885 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7886 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7887 address = if index then offset_addr else R[n];
7888 data = MemU[address,2];
7889 if wback then R[n] = offset_addr;
7890 if UnalignedSupport() || address<0> = '0' then
7891 R[t] = SignExtend(data, 32);
7892 else // Can only apply before ARMv7
7893 R[t] = bits(32) UNKNOWN;
7894 #endif
7896 bool success = false;
7898 if (ConditionPassed(opcode)) {
7899 uint32_t t;
7900 uint32_t n;
7901 uint32_t imm32;
7902 bool index;
7903 bool add;
7904 bool wback;
7906 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7907 switch (encoding) {
7908 case eEncodingT1:
7909 // if Rn == '1111' then SEE LDRSH (literal);
7910 // if Rt == '1111' then SEE "Unallocated memory hints";
7911 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7912 t = Bits32(opcode, 15, 12);
7913 n = Bits32(opcode, 19, 16);
7914 imm32 = Bits32(opcode, 11, 0);
7916 // index = TRUE; add = TRUE; wback = FALSE;
7917 index = true;
7918 add = true;
7919 wback = false;
7921 // if t == 13 then UNPREDICTABLE;
7922 if (t == 13)
7923 return false;
7925 break;
7927 case eEncodingT2:
7928 // if Rn == '1111' then SEE LDRSH (literal);
7929 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE
7930 // "Unallocated memory hints";
7931 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7932 // if P == '0' && W == '0' then UNDEFINED;
7933 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
7934 return false;
7936 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7937 t = Bits32(opcode, 15, 12);
7938 n = Bits32(opcode, 19, 16);
7939 imm32 = Bits32(opcode, 7, 0);
7941 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7942 index = BitIsSet(opcode, 10);
7943 add = BitIsSet(opcode, 9);
7944 wback = BitIsSet(opcode, 8);
7946 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7947 if (BadReg(t) || (wback && (n == t)))
7948 return false;
7950 break;
7952 case eEncodingA1: {
7953 // if Rn == '1111' then SEE LDRSH (literal);
7954 // if P == '0' && W == '1' then SEE LDRSHT;
7955 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7956 t = Bits32(opcode, 15, 12);
7957 n = Bits32(opcode, 19, 16);
7958 uint32_t imm4H = Bits32(opcode, 11, 8);
7959 uint32_t imm4L = Bits32(opcode, 3, 0);
7960 imm32 = (imm4H << 4) | imm4L;
7962 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7963 // (W == '1');
7964 index = BitIsSet(opcode, 24);
7965 add = BitIsSet(opcode, 23);
7966 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
7968 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7969 if ((t == 15) || (wback && (n == t)))
7970 return false;
7972 break;
7975 default:
7976 return false;
7979 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7980 uint64_t Rn =
7981 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7982 if (!success)
7983 return false;
7985 addr_t offset_addr;
7986 if (add)
7987 offset_addr = Rn + imm32;
7988 else
7989 offset_addr = Rn - imm32;
7991 // address = if index then offset_addr else R[n];
7992 addr_t address;
7993 if (index)
7994 address = offset_addr;
7995 else
7996 address = Rn;
7998 // data = MemU[address,2];
7999 std::optional<RegisterInfo> base_reg =
8000 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
8002 EmulateInstruction::Context context;
8003 context.type = eContextRegisterLoad;
8004 context.SetRegisterPlusOffset(*base_reg, address - Rn);
8006 uint64_t data = MemURead(context, address, 2, 0, &success);
8007 if (!success)
8008 return false;
8010 // if wback then R[n] = offset_addr;
8011 if (wback) {
8012 context.type = eContextAdjustBaseRegister;
8013 context.SetAddress(offset_addr);
8014 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8015 offset_addr))
8016 return false;
8019 // if UnalignedSupport() || address<0> = '0' then
8020 if (UnalignedSupport() || BitIsClear(address, 0)) {
8021 // R[t] = SignExtend(data, 32);
8022 int64_t signed_data = llvm::SignExtend64<16>(data);
8023 context.type = eContextRegisterLoad;
8024 context.SetRegisterPlusOffset(*base_reg, address - Rn);
8025 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
8026 (uint64_t)signed_data))
8027 return false;
8028 } else // Can only apply before ARMv7
8030 // R[t] = bits(32) UNKNOWN;
8031 WriteBits32Unknown(t);
8034 return true;
8037 // LDRSH (literal) calculates an address from the PC value and an immediate
8038 // offset, loads a halfword from memory,
8039 // sign-extends it to from a 32-bit word, and writes it to a register.
8040 bool EmulateInstructionARM::EmulateLDRSHLiteral(const uint32_t opcode,
8041 const ARMEncoding encoding) {
8042 #if 0
8043 if ConditionPassed() then
8044 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
8045 base = Align(PC,4);
8046 address = if add then (base + imm32) else (base - imm32);
8047 data = MemU[address,2];
8048 if UnalignedSupport() || address<0> = '0' then
8049 R[t] = SignExtend(data, 32);
8050 else // Can only apply before ARMv7
8051 R[t] = bits(32) UNKNOWN;
8052 #endif
8054 bool success = false;
8056 if (ConditionPassed(opcode)) {
8057 uint32_t t;
8058 uint32_t imm32;
8059 bool add;
8061 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
8062 switch (encoding) {
8063 case eEncodingT1:
8064 // if Rt == '1111' then SEE "Unallocated memory hints";
8065 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
8066 t = Bits32(opcode, 15, 12);
8067 imm32 = Bits32(opcode, 11, 0);
8068 add = BitIsSet(opcode, 23);
8070 // if t == 13 then UNPREDICTABLE;
8071 if (t == 13)
8072 return false;
8074 break;
8076 case eEncodingA1: {
8077 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
8078 t = Bits32(opcode, 15, 12);
8079 uint32_t imm4H = Bits32(opcode, 11, 8);
8080 uint32_t imm4L = Bits32(opcode, 3, 0);
8081 imm32 = (imm4H << 4) | imm4L;
8082 add = BitIsSet(opcode, 23);
8084 // if t == 15 then UNPREDICTABLE;
8085 if (t == 15)
8086 return false;
8088 break;
8090 default:
8091 return false;
8094 // base = Align(PC,4);
8095 uint64_t pc_value = ReadCoreReg(PC_REG, &success);
8096 if (!success)
8097 return false;
8099 uint64_t base = AlignPC(pc_value);
8101 addr_t address;
8102 // address = if add then (base + imm32) else (base - imm32);
8103 if (add)
8104 address = base + imm32;
8105 else
8106 address = base - imm32;
8108 // data = MemU[address,2];
8109 std::optional<RegisterInfo> base_reg =
8110 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
8112 EmulateInstruction::Context context;
8113 context.type = eContextRegisterLoad;
8114 context.SetRegisterPlusOffset(*base_reg, imm32);
8116 uint64_t data = MemURead(context, address, 2, 0, &success);
8117 if (!success)
8118 return false;
8120 // if UnalignedSupport() || address<0> = '0' then
8121 if (UnalignedSupport() || BitIsClear(address, 0)) {
8122 // R[t] = SignExtend(data, 32);
8123 int64_t signed_data = llvm::SignExtend64<16>(data);
8124 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
8125 (uint64_t)signed_data))
8126 return false;
8127 } else // Can only apply before ARMv7
8129 // R[t] = bits(32) UNKNOWN;
8130 WriteBits32Unknown(t);
8133 return true;
8136 // LDRSH (register) calculates an address from a base register value and an
8137 // offset register value, loads a halfword
8138 // from memory, sign-extends it to form a 32-bit word, and writes it to a
8139 // register. The offset register value can be shifted left by 0, 1, 2, or 3
8140 // bits.
8141 bool EmulateInstructionARM::EmulateLDRSHRegister(const uint32_t opcode,
8142 const ARMEncoding encoding) {
8143 #if 0
8144 if ConditionPassed() then
8145 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
8146 offset = Shift(R[m], shift_t, shift_n, APSR.C);
8147 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
8148 address = if index then offset_addr else R[n];
8149 data = MemU[address,2];
8150 if wback then R[n] = offset_addr;
8151 if UnalignedSupport() || address<0> = '0' then
8152 R[t] = SignExtend(data, 32);
8153 else // Can only apply before ARMv7
8154 R[t] = bits(32) UNKNOWN;
8155 #endif
8157 bool success = false;
8159 if (ConditionPassed(opcode)) {
8160 uint32_t t;
8161 uint32_t n;
8162 uint32_t m;
8163 bool index;
8164 bool add;
8165 bool wback;
8166 ARM_ShifterType shift_t;
8167 uint32_t shift_n;
8169 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
8170 switch (encoding) {
8171 case eEncodingT1:
8172 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
8173 // in ThumbEE";
8174 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8175 t = Bits32(opcode, 2, 0);
8176 n = Bits32(opcode, 5, 3);
8177 m = Bits32(opcode, 8, 6);
8179 // index = TRUE; add = TRUE; wback = FALSE;
8180 index = true;
8181 add = true;
8182 wback = false;
8184 // (shift_t, shift_n) = (SRType_LSL, 0);
8185 shift_t = SRType_LSL;
8186 shift_n = 0;
8188 break;
8190 case eEncodingT2:
8191 // if Rn == '1111' then SEE LDRSH (literal);
8192 // if Rt == '1111' then SEE "Unallocated memory hints";
8193 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8194 t = Bits32(opcode, 15, 12);
8195 n = Bits32(opcode, 19, 16);
8196 m = Bits32(opcode, 3, 0);
8198 // index = TRUE; add = TRUE; wback = FALSE;
8199 index = true;
8200 add = true;
8201 wback = false;
8203 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
8204 shift_t = SRType_LSL;
8205 shift_n = Bits32(opcode, 5, 4);
8207 // if t == 13 || BadReg(m) then UNPREDICTABLE;
8208 if ((t == 13) || BadReg(m))
8209 return false;
8211 break;
8213 case eEncodingA1:
8214 // if P == '0' && W == '1' then SEE LDRSHT;
8215 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8216 t = Bits32(opcode, 15, 12);
8217 n = Bits32(opcode, 19, 16);
8218 m = Bits32(opcode, 3, 0);
8220 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
8221 // (W == '1');
8222 index = BitIsSet(opcode, 24);
8223 add = BitIsSet(opcode, 23);
8224 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
8226 // (shift_t, shift_n) = (SRType_LSL, 0);
8227 shift_t = SRType_LSL;
8228 shift_n = 0;
8230 // if t == 15 || m == 15 then UNPREDICTABLE;
8231 if ((t == 15) || (m == 15))
8232 return false;
8234 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
8235 if (wback && ((n == 15) || (n == t)))
8236 return false;
8238 break;
8240 default:
8241 return false;
8244 uint64_t Rm =
8245 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8246 if (!success)
8247 return false;
8249 uint64_t Rn =
8250 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8251 if (!success)
8252 return false;
8254 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
8255 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
8256 if (!success)
8257 return false;
8259 addr_t offset_addr;
8260 addr_t address;
8262 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
8263 if (add)
8264 offset_addr = Rn + offset;
8265 else
8266 offset_addr = Rn - offset;
8268 // address = if index then offset_addr else R[n];
8269 if (index)
8270 address = offset_addr;
8271 else
8272 address = Rn;
8274 // data = MemU[address,2];
8275 std::optional<RegisterInfo> base_reg =
8276 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
8277 std::optional<RegisterInfo> offset_reg =
8278 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
8280 EmulateInstruction::Context context;
8281 context.type = eContextRegisterLoad;
8282 context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg);
8284 uint64_t data = MemURead(context, address, 2, 0, &success);
8285 if (!success)
8286 return false;
8288 // if wback then R[n] = offset_addr;
8289 if (wback) {
8290 context.type = eContextAdjustBaseRegister;
8291 context.SetAddress(offset_addr);
8292 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8293 offset_addr))
8294 return false;
8297 // if UnalignedSupport() || address<0> = '0' then
8298 if (UnalignedSupport() || BitIsClear(address, 0)) {
8299 // R[t] = SignExtend(data, 32);
8300 context.type = eContextRegisterLoad;
8301 context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg);
8303 int64_t signed_data = llvm::SignExtend64<16>(data);
8304 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
8305 (uint64_t)signed_data))
8306 return false;
8307 } else // Can only apply before ARMv7
8309 // R[t] = bits(32) UNKNOWN;
8310 WriteBits32Unknown(t);
8313 return true;
8316 // SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and
8317 // writes the result to the destination
8318 // register. You can specifiy a rotation by 0, 8, 16, or 24 bits before
8319 // extracting the 8-bit value.
8320 bool EmulateInstructionARM::EmulateSXTB(const uint32_t opcode,
8321 const ARMEncoding encoding) {
8322 #if 0
8323 if ConditionPassed() then
8324 EncodingSpecificOperations();
8325 rotated = ROR(R[m], rotation);
8326 R[d] = SignExtend(rotated<7:0>, 32);
8327 #endif
8329 bool success = false;
8331 if (ConditionPassed(opcode)) {
8332 uint32_t d;
8333 uint32_t m;
8334 uint32_t rotation;
8336 // EncodingSpecificOperations();
8337 switch (encoding) {
8338 case eEncodingT1:
8339 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8340 d = Bits32(opcode, 2, 0);
8341 m = Bits32(opcode, 5, 3);
8342 rotation = 0;
8344 break;
8346 case eEncodingT2:
8347 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8348 d = Bits32(opcode, 11, 8);
8349 m = Bits32(opcode, 3, 0);
8350 rotation = Bits32(opcode, 5, 4) << 3;
8352 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8353 if (BadReg(d) || BadReg(m))
8354 return false;
8356 break;
8358 case eEncodingA1:
8359 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8360 d = Bits32(opcode, 15, 12);
8361 m = Bits32(opcode, 3, 0);
8362 rotation = Bits32(opcode, 11, 10) << 3;
8364 // if d == 15 || m == 15 then UNPREDICTABLE;
8365 if ((d == 15) || (m == 15))
8366 return false;
8368 break;
8370 default:
8371 return false;
8374 uint64_t Rm =
8375 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8376 if (!success)
8377 return false;
8379 // rotated = ROR(R[m], rotation);
8380 uint64_t rotated = ROR(Rm, rotation, &success);
8381 if (!success)
8382 return false;
8384 // R[d] = SignExtend(rotated<7:0>, 32);
8385 int64_t data = llvm::SignExtend64<8>(rotated);
8387 std::optional<RegisterInfo> source_reg =
8388 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
8390 EmulateInstruction::Context context;
8391 context.type = eContextRegisterLoad;
8392 context.SetRegister(*source_reg);
8394 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8395 (uint64_t)data))
8396 return false;
8398 return true;
8401 // SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and
8402 // writes the result to the destination
8403 // register. You can specify a rotation by 0, 8, 16, or 24 bits before
8404 // extracting the 16-bit value.
8405 bool EmulateInstructionARM::EmulateSXTH(const uint32_t opcode,
8406 const ARMEncoding encoding) {
8407 #if 0
8408 if ConditionPassed() then
8409 EncodingSpecificOperations();
8410 rotated = ROR(R[m], rotation);
8411 R[d] = SignExtend(rotated<15:0>, 32);
8412 #endif
8414 bool success = false;
8416 if (ConditionPassed(opcode)) {
8417 uint32_t d;
8418 uint32_t m;
8419 uint32_t rotation;
8421 // EncodingSpecificOperations();
8422 switch (encoding) {
8423 case eEncodingT1:
8424 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8425 d = Bits32(opcode, 2, 0);
8426 m = Bits32(opcode, 5, 3);
8427 rotation = 0;
8429 break;
8431 case eEncodingT2:
8432 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8433 d = Bits32(opcode, 11, 8);
8434 m = Bits32(opcode, 3, 0);
8435 rotation = Bits32(opcode, 5, 4) << 3;
8437 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8438 if (BadReg(d) || BadReg(m))
8439 return false;
8441 break;
8443 case eEncodingA1:
8444 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8445 d = Bits32(opcode, 15, 12);
8446 m = Bits32(opcode, 3, 0);
8447 rotation = Bits32(opcode, 11, 10) << 3;
8449 // if d == 15 || m == 15 then UNPREDICTABLE;
8450 if ((d == 15) || (m == 15))
8451 return false;
8453 break;
8455 default:
8456 return false;
8459 uint64_t Rm =
8460 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8461 if (!success)
8462 return false;
8464 // rotated = ROR(R[m], rotation);
8465 uint64_t rotated = ROR(Rm, rotation, &success);
8466 if (!success)
8467 return false;
8469 // R[d] = SignExtend(rotated<15:0>, 32);
8470 std::optional<RegisterInfo> source_reg =
8471 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
8473 EmulateInstruction::Context context;
8474 context.type = eContextRegisterLoad;
8475 context.SetRegister(*source_reg);
8477 int64_t data = llvm::SignExtend64<16>(rotated);
8478 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8479 (uint64_t)data))
8480 return false;
8483 return true;
8486 // UXTB extracts an 8-bit value from a register, zero-extends it to 32 bits, and
8487 // writes the result to the destination
8488 // register. You can specify a rotation by 0, 8, 16, or 24 bits before
8489 // extracting the 8-bit value.
8490 bool EmulateInstructionARM::EmulateUXTB(const uint32_t opcode,
8491 const ARMEncoding encoding) {
8492 #if 0
8493 if ConditionPassed() then
8494 EncodingSpecificOperations();
8495 rotated = ROR(R[m], rotation);
8496 R[d] = ZeroExtend(rotated<7:0>, 32);
8497 #endif
8499 bool success = false;
8501 if (ConditionPassed(opcode)) {
8502 uint32_t d;
8503 uint32_t m;
8504 uint32_t rotation;
8506 // EncodingSpecificOperations();
8507 switch (encoding) {
8508 case eEncodingT1:
8509 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8510 d = Bits32(opcode, 2, 0);
8511 m = Bits32(opcode, 5, 3);
8512 rotation = 0;
8514 break;
8516 case eEncodingT2:
8517 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8518 d = Bits32(opcode, 11, 8);
8519 m = Bits32(opcode, 3, 0);
8520 rotation = Bits32(opcode, 5, 4) << 3;
8522 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8523 if (BadReg(d) || BadReg(m))
8524 return false;
8526 break;
8528 case eEncodingA1:
8529 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8530 d = Bits32(opcode, 15, 12);
8531 m = Bits32(opcode, 3, 0);
8532 rotation = Bits32(opcode, 11, 10) << 3;
8534 // if d == 15 || m == 15 then UNPREDICTABLE;
8535 if ((d == 15) || (m == 15))
8536 return false;
8538 break;
8540 default:
8541 return false;
8544 uint64_t Rm =
8545 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8546 if (!success)
8547 return false;
8549 // rotated = ROR(R[m], rotation);
8550 uint64_t rotated = ROR(Rm, rotation, &success);
8551 if (!success)
8552 return false;
8554 // R[d] = ZeroExtend(rotated<7:0>, 32);
8555 std::optional<RegisterInfo> source_reg =
8556 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
8558 EmulateInstruction::Context context;
8559 context.type = eContextRegisterLoad;
8560 context.SetRegister(*source_reg);
8562 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8563 Bits32(rotated, 7, 0)))
8564 return false;
8566 return true;
8569 // UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and
8570 // writes the result to the destination
8571 // register. You can specify a rotation by 0, 8, 16, or 24 bits before
8572 // extracting the 16-bit value.
8573 bool EmulateInstructionARM::EmulateUXTH(const uint32_t opcode,
8574 const ARMEncoding encoding) {
8575 #if 0
8576 if ConditionPassed() then
8577 EncodingSpecificOperations();
8578 rotated = ROR(R[m], rotation);
8579 R[d] = ZeroExtend(rotated<15:0>, 32);
8580 #endif
8582 bool success = false;
8584 if (ConditionPassed(opcode)) {
8585 uint32_t d;
8586 uint32_t m;
8587 uint32_t rotation;
8589 switch (encoding) {
8590 case eEncodingT1:
8591 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8592 d = Bits32(opcode, 2, 0);
8593 m = Bits32(opcode, 5, 3);
8594 rotation = 0;
8596 break;
8598 case eEncodingT2:
8599 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8600 d = Bits32(opcode, 11, 8);
8601 m = Bits32(opcode, 3, 0);
8602 rotation = Bits32(opcode, 5, 4) << 3;
8604 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8605 if (BadReg(d) || BadReg(m))
8606 return false;
8608 break;
8610 case eEncodingA1:
8611 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8612 d = Bits32(opcode, 15, 12);
8613 m = Bits32(opcode, 3, 0);
8614 rotation = Bits32(opcode, 11, 10) << 3;
8616 // if d == 15 || m == 15 then UNPREDICTABLE;
8617 if ((d == 15) || (m == 15))
8618 return false;
8620 break;
8622 default:
8623 return false;
8626 uint64_t Rm =
8627 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8628 if (!success)
8629 return false;
8631 // rotated = ROR(R[m], rotation);
8632 uint64_t rotated = ROR(Rm, rotation, &success);
8633 if (!success)
8634 return false;
8636 // R[d] = ZeroExtend(rotated<15:0>, 32);
8637 std::optional<RegisterInfo> source_reg =
8638 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
8640 EmulateInstruction::Context context;
8641 context.type = eContextRegisterLoad;
8642 context.SetRegister(*source_reg);
8644 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8645 Bits32(rotated, 15, 0)))
8646 return false;
8648 return true;
8651 // RFE (Return From Exception) loads the PC and the CPSR from the word at the
8652 // specified address and the following
8653 // word respectively.
8654 bool EmulateInstructionARM::EmulateRFE(const uint32_t opcode,
8655 const ARMEncoding encoding) {
8656 #if 0
8657 if ConditionPassed() then
8658 EncodingSpecificOperations();
8659 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8660 UNPREDICTABLE;
8661 else
8662 address = if increment then R[n] else R[n]-8;
8663 if wordhigher then address = address+4;
8664 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
8665 BranchWritePC(MemA[address,4]);
8666 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8667 #endif
8669 bool success = false;
8671 if (ConditionPassed(opcode)) {
8672 uint32_t n;
8673 bool wback;
8674 bool increment;
8675 bool wordhigher;
8677 // EncodingSpecificOperations();
8678 switch (encoding) {
8679 case eEncodingT1:
8680 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher =
8681 // FALSE;
8682 n = Bits32(opcode, 19, 16);
8683 wback = BitIsSet(opcode, 21);
8684 increment = false;
8685 wordhigher = false;
8687 // if n == 15 then UNPREDICTABLE;
8688 if (n == 15)
8689 return false;
8691 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8692 if (InITBlock() && !LastInITBlock())
8693 return false;
8695 break;
8697 case eEncodingT2:
8698 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
8699 n = Bits32(opcode, 19, 16);
8700 wback = BitIsSet(opcode, 21);
8701 increment = true;
8702 wordhigher = false;
8704 // if n == 15 then UNPREDICTABLE;
8705 if (n == 15)
8706 return false;
8708 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8709 if (InITBlock() && !LastInITBlock())
8710 return false;
8712 break;
8714 case eEncodingA1:
8715 // n = UInt(Rn);
8716 n = Bits32(opcode, 19, 16);
8718 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
8719 wback = BitIsSet(opcode, 21);
8720 increment = BitIsSet(opcode, 23);
8721 wordhigher = (Bit32(opcode, 24) == Bit32(opcode, 23));
8723 // if n == 15 then UNPREDICTABLE;
8724 if (n == 15)
8725 return false;
8727 break;
8729 default:
8730 return false;
8733 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE
8734 // then
8735 if (!CurrentModeIsPrivileged())
8736 // UNPREDICTABLE;
8737 return false;
8738 else {
8739 uint64_t Rn =
8740 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8741 if (!success)
8742 return false;
8744 addr_t address;
8745 // address = if increment then R[n] else R[n]-8;
8746 if (increment)
8747 address = Rn;
8748 else
8749 address = Rn - 8;
8751 // if wordhigher then address = address+4;
8752 if (wordhigher)
8753 address = address + 4;
8755 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
8756 std::optional<RegisterInfo> base_reg =
8757 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
8759 EmulateInstruction::Context context;
8760 context.type = eContextReturnFromException;
8761 context.SetRegisterPlusOffset(*base_reg, address - Rn);
8763 uint64_t data = MemARead(context, address + 4, 4, 0, &success);
8764 if (!success)
8765 return false;
8767 CPSRWriteByInstr(data, 15, true);
8769 // BranchWritePC(MemA[address,4]);
8770 uint64_t data2 = MemARead(context, address, 4, 0, &success);
8771 if (!success)
8772 return false;
8774 BranchWritePC(context, data2);
8776 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8777 if (wback) {
8778 context.type = eContextAdjustBaseRegister;
8779 if (increment) {
8780 context.SetOffset(8);
8781 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8782 Rn + 8))
8783 return false;
8784 } else {
8785 context.SetOffset(-8);
8786 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8787 Rn - 8))
8788 return false;
8790 } // if wback
8792 } // if ConditionPassed()
8793 return true;
8796 // Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a
8797 // register value and an immediate value, and writes the result to the
8798 // destination register. It can optionally update the condition flags based on
8799 // the result.
8800 bool EmulateInstructionARM::EmulateEORImm(const uint32_t opcode,
8801 const ARMEncoding encoding) {
8802 #if 0
8803 // ARM pseudo code...
8804 if ConditionPassed() then
8805 EncodingSpecificOperations();
8806 result = R[n] EOR imm32;
8807 if d == 15 then // Can only occur for ARM encoding
8808 ALUWritePC(result); // setflags is always FALSE here
8809 else
8810 R[d] = result;
8811 if setflags then
8812 APSR.N = result<31>;
8813 APSR.Z = IsZeroBit(result);
8814 APSR.C = carry;
8815 // APSR.V unchanged
8816 #endif
8818 bool success = false;
8820 if (ConditionPassed(opcode)) {
8821 uint32_t Rd, Rn;
8822 uint32_t
8823 imm32; // the immediate value to be ORed to the value obtained from Rn
8824 bool setflags;
8825 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8826 switch (encoding) {
8827 case eEncodingT1:
8828 Rd = Bits32(opcode, 11, 8);
8829 Rn = Bits32(opcode, 19, 16);
8830 setflags = BitIsSet(opcode, 20);
8831 imm32 = ThumbExpandImm_C(
8832 opcode, APSR_C,
8833 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8834 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8835 if (Rd == 15 && setflags)
8836 return EmulateTEQImm(opcode, eEncodingT1);
8837 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8838 return false;
8839 break;
8840 case eEncodingA1:
8841 Rd = Bits32(opcode, 15, 12);
8842 Rn = Bits32(opcode, 19, 16);
8843 setflags = BitIsSet(opcode, 20);
8844 imm32 =
8845 ARMExpandImm_C(opcode, APSR_C,
8846 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8848 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
8849 // instructions;
8850 if (Rd == 15 && setflags)
8851 return EmulateSUBSPcLrEtc(opcode, encoding);
8852 break;
8853 default:
8854 return false;
8857 // Read the first operand.
8858 uint32_t val1 = ReadCoreReg(Rn, &success);
8859 if (!success)
8860 return false;
8862 uint32_t result = val1 ^ imm32;
8864 EmulateInstruction::Context context;
8865 context.type = EmulateInstruction::eContextImmediate;
8866 context.SetNoArgs();
8868 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8869 return false;
8871 return true;
8874 // Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a
8875 // register value and an optionally-shifted register value, and writes the
8876 // result to the destination register. It can optionally update the condition
8877 // flags based on the result.
8878 bool EmulateInstructionARM::EmulateEORReg(const uint32_t opcode,
8879 const ARMEncoding encoding) {
8880 #if 0
8881 // ARM pseudo code...
8882 if ConditionPassed() then
8883 EncodingSpecificOperations();
8884 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8885 result = R[n] EOR shifted;
8886 if d == 15 then // Can only occur for ARM encoding
8887 ALUWritePC(result); // setflags is always FALSE here
8888 else
8889 R[d] = result;
8890 if setflags then
8891 APSR.N = result<31>;
8892 APSR.Z = IsZeroBit(result);
8893 APSR.C = carry;
8894 // APSR.V unchanged
8895 #endif
8897 bool success = false;
8899 if (ConditionPassed(opcode)) {
8900 uint32_t Rd, Rn, Rm;
8901 ARM_ShifterType shift_t;
8902 uint32_t shift_n; // the shift applied to the value read from Rm
8903 bool setflags;
8904 uint32_t carry;
8905 switch (encoding) {
8906 case eEncodingT1:
8907 Rd = Rn = Bits32(opcode, 2, 0);
8908 Rm = Bits32(opcode, 5, 3);
8909 setflags = !InITBlock();
8910 shift_t = SRType_LSL;
8911 shift_n = 0;
8912 break;
8913 case eEncodingT2:
8914 Rd = Bits32(opcode, 11, 8);
8915 Rn = Bits32(opcode, 19, 16);
8916 Rm = Bits32(opcode, 3, 0);
8917 setflags = BitIsSet(opcode, 20);
8918 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8919 // if Rd == '1111' && S == '1' then SEE TEQ (register);
8920 if (Rd == 15 && setflags)
8921 return EmulateTEQReg(opcode, eEncodingT1);
8922 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8923 return false;
8924 break;
8925 case eEncodingA1:
8926 Rd = Bits32(opcode, 15, 12);
8927 Rn = Bits32(opcode, 19, 16);
8928 Rm = Bits32(opcode, 3, 0);
8929 setflags = BitIsSet(opcode, 20);
8930 shift_n = DecodeImmShiftARM(opcode, shift_t);
8932 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
8933 // instructions;
8934 if (Rd == 15 && setflags)
8935 return EmulateSUBSPcLrEtc(opcode, encoding);
8936 break;
8937 default:
8938 return false;
8941 // Read the first operand.
8942 uint32_t val1 = ReadCoreReg(Rn, &success);
8943 if (!success)
8944 return false;
8946 // Read the second operand.
8947 uint32_t val2 = ReadCoreReg(Rm, &success);
8948 if (!success)
8949 return false;
8951 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
8952 if (!success)
8953 return false;
8954 uint32_t result = val1 ^ shifted;
8956 EmulateInstruction::Context context;
8957 context.type = EmulateInstruction::eContextImmediate;
8958 context.SetNoArgs();
8960 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8961 return false;
8963 return true;
8966 // Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value
8967 // and an immediate value, and writes the result to the destination register.
8968 // It can optionally update the condition flags based on the result.
8969 bool EmulateInstructionARM::EmulateORRImm(const uint32_t opcode,
8970 const ARMEncoding encoding) {
8971 #if 0
8972 // ARM pseudo code...
8973 if ConditionPassed() then
8974 EncodingSpecificOperations();
8975 result = R[n] OR imm32;
8976 if d == 15 then // Can only occur for ARM encoding
8977 ALUWritePC(result); // setflags is always FALSE here
8978 else
8979 R[d] = result;
8980 if setflags then
8981 APSR.N = result<31>;
8982 APSR.Z = IsZeroBit(result);
8983 APSR.C = carry;
8984 // APSR.V unchanged
8985 #endif
8987 bool success = false;
8989 if (ConditionPassed(opcode)) {
8990 uint32_t Rd, Rn;
8991 uint32_t
8992 imm32; // the immediate value to be ORed to the value obtained from Rn
8993 bool setflags;
8994 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8995 switch (encoding) {
8996 case eEncodingT1:
8997 Rd = Bits32(opcode, 11, 8);
8998 Rn = Bits32(opcode, 19, 16);
8999 setflags = BitIsSet(opcode, 20);
9000 imm32 = ThumbExpandImm_C(
9001 opcode, APSR_C,
9002 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9003 // if Rn == '1111' then SEE MOV (immediate);
9004 if (Rn == 15)
9005 return EmulateMOVRdImm(opcode, eEncodingT2);
9006 if (BadReg(Rd) || Rn == 13)
9007 return false;
9008 break;
9009 case eEncodingA1:
9010 Rd = Bits32(opcode, 15, 12);
9011 Rn = Bits32(opcode, 19, 16);
9012 setflags = BitIsSet(opcode, 20);
9013 imm32 =
9014 ARMExpandImm_C(opcode, APSR_C,
9015 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9017 if (Rd == 15 && setflags)
9018 return EmulateSUBSPcLrEtc(opcode, encoding);
9019 break;
9020 default:
9021 return false;
9024 // Read the first operand.
9025 uint32_t val1 = ReadCoreReg(Rn, &success);
9026 if (!success)
9027 return false;
9029 uint32_t result = val1 | imm32;
9031 EmulateInstruction::Context context;
9032 context.type = EmulateInstruction::eContextImmediate;
9033 context.SetNoArgs();
9035 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
9036 return false;
9038 return true;
9041 // Bitwise OR (register) performs a bitwise (inclusive) OR of a register value
9042 // and an optionally-shifted register value, and writes the result to the
9043 // destination register. It can optionally update the condition flags based on
9044 // the result.
9045 bool EmulateInstructionARM::EmulateORRReg(const uint32_t opcode,
9046 const ARMEncoding encoding) {
9047 #if 0
9048 // ARM pseudo code...
9049 if ConditionPassed() then
9050 EncodingSpecificOperations();
9051 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9052 result = R[n] OR shifted;
9053 if d == 15 then // Can only occur for ARM encoding
9054 ALUWritePC(result); // setflags is always FALSE here
9055 else
9056 R[d] = result;
9057 if setflags then
9058 APSR.N = result<31>;
9059 APSR.Z = IsZeroBit(result);
9060 APSR.C = carry;
9061 // APSR.V unchanged
9062 #endif
9064 bool success = false;
9066 if (ConditionPassed(opcode)) {
9067 uint32_t Rd, Rn, Rm;
9068 ARM_ShifterType shift_t;
9069 uint32_t shift_n; // the shift applied to the value read from Rm
9070 bool setflags;
9071 uint32_t carry;
9072 switch (encoding) {
9073 case eEncodingT1:
9074 Rd = Rn = Bits32(opcode, 2, 0);
9075 Rm = Bits32(opcode, 5, 3);
9076 setflags = !InITBlock();
9077 shift_t = SRType_LSL;
9078 shift_n = 0;
9079 break;
9080 case eEncodingT2:
9081 Rd = Bits32(opcode, 11, 8);
9082 Rn = Bits32(opcode, 19, 16);
9083 Rm = Bits32(opcode, 3, 0);
9084 setflags = BitIsSet(opcode, 20);
9085 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9086 // if Rn == '1111' then SEE MOV (register);
9087 if (Rn == 15)
9088 return EmulateMOVRdRm(opcode, eEncodingT3);
9089 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
9090 return false;
9091 break;
9092 case eEncodingA1:
9093 Rd = Bits32(opcode, 15, 12);
9094 Rn = Bits32(opcode, 19, 16);
9095 Rm = Bits32(opcode, 3, 0);
9096 setflags = BitIsSet(opcode, 20);
9097 shift_n = DecodeImmShiftARM(opcode, shift_t);
9099 if (Rd == 15 && setflags)
9100 return EmulateSUBSPcLrEtc(opcode, encoding);
9101 break;
9102 default:
9103 return false;
9106 // Read the first operand.
9107 uint32_t val1 = ReadCoreReg(Rn, &success);
9108 if (!success)
9109 return false;
9111 // Read the second operand.
9112 uint32_t val2 = ReadCoreReg(Rm, &success);
9113 if (!success)
9114 return false;
9116 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9117 if (!success)
9118 return false;
9119 uint32_t result = val1 | shifted;
9121 EmulateInstruction::Context context;
9122 context.type = EmulateInstruction::eContextImmediate;
9123 context.SetNoArgs();
9125 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
9126 return false;
9128 return true;
9131 // Reverse Subtract (immediate) subtracts a register value from an immediate
9132 // value, and writes the result to the destination register. It can optionally
9133 // update the condition flags based on the result.
9134 bool EmulateInstructionARM::EmulateRSBImm(const uint32_t opcode,
9135 const ARMEncoding encoding) {
9136 #if 0
9137 // ARM pseudo code...
9138 if ConditionPassed() then
9139 EncodingSpecificOperations();
9140 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
9141 if d == 15 then // Can only occur for ARM encoding
9142 ALUWritePC(result); // setflags is always FALSE here
9143 else
9144 R[d] = result;
9145 if setflags then
9146 APSR.N = result<31>;
9147 APSR.Z = IsZeroBit(result);
9148 APSR.C = carry;
9149 APSR.V = overflow;
9150 #endif
9152 bool success = false;
9154 uint32_t Rd; // the destination register
9155 uint32_t Rn; // the first operand
9156 bool setflags;
9157 uint32_t
9158 imm32; // the immediate value to be added to the value obtained from Rn
9159 switch (encoding) {
9160 case eEncodingT1:
9161 Rd = Bits32(opcode, 2, 0);
9162 Rn = Bits32(opcode, 5, 3);
9163 setflags = !InITBlock();
9164 imm32 = 0;
9165 break;
9166 case eEncodingT2:
9167 Rd = Bits32(opcode, 11, 8);
9168 Rn = Bits32(opcode, 19, 16);
9169 setflags = BitIsSet(opcode, 20);
9170 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9171 if (BadReg(Rd) || BadReg(Rn))
9172 return false;
9173 break;
9174 case eEncodingA1:
9175 Rd = Bits32(opcode, 15, 12);
9176 Rn = Bits32(opcode, 19, 16);
9177 setflags = BitIsSet(opcode, 20);
9178 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9180 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9181 // instructions;
9182 if (Rd == 15 && setflags)
9183 return EmulateSUBSPcLrEtc(opcode, encoding);
9184 break;
9185 default:
9186 return false;
9188 // Read the register value from the operand register Rn.
9189 uint32_t reg_val = ReadCoreReg(Rn, &success);
9190 if (!success)
9191 return false;
9193 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
9195 EmulateInstruction::Context context;
9196 context.type = EmulateInstruction::eContextImmediate;
9197 context.SetNoArgs();
9199 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9200 res.carry_out, res.overflow);
9203 // Reverse Subtract (register) subtracts a register value from an optionally-
9204 // shifted register value, and writes the result to the destination register.
9205 // It can optionally update the condition flags based on the result.
9206 bool EmulateInstructionARM::EmulateRSBReg(const uint32_t opcode,
9207 const ARMEncoding encoding) {
9208 #if 0
9209 // ARM pseudo code...
9210 if ConditionPassed() then
9211 EncodingSpecificOperations();
9212 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9213 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
9214 if d == 15 then // Can only occur for ARM encoding
9215 ALUWritePC(result); // setflags is always FALSE here
9216 else
9217 R[d] = result;
9218 if setflags then
9219 APSR.N = result<31>;
9220 APSR.Z = IsZeroBit(result);
9221 APSR.C = carry;
9222 APSR.V = overflow;
9223 #endif
9225 bool success = false;
9227 uint32_t Rd; // the destination register
9228 uint32_t Rn; // the first operand
9229 uint32_t Rm; // the second operand
9230 bool setflags;
9231 ARM_ShifterType shift_t;
9232 uint32_t shift_n; // the shift applied to the value read from Rm
9233 switch (encoding) {
9234 case eEncodingT1:
9235 Rd = Bits32(opcode, 11, 8);
9236 Rn = Bits32(opcode, 19, 16);
9237 Rm = Bits32(opcode, 3, 0);
9238 setflags = BitIsSet(opcode, 20);
9239 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9240 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
9241 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
9242 return false;
9243 break;
9244 case eEncodingA1:
9245 Rd = Bits32(opcode, 15, 12);
9246 Rn = Bits32(opcode, 19, 16);
9247 Rm = Bits32(opcode, 3, 0);
9248 setflags = BitIsSet(opcode, 20);
9249 shift_n = DecodeImmShiftARM(opcode, shift_t);
9251 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9252 // instructions;
9253 if (Rd == 15 && setflags)
9254 return EmulateSUBSPcLrEtc(opcode, encoding);
9255 break;
9256 default:
9257 return false;
9259 // Read the register value from register Rn.
9260 uint32_t val1 = ReadCoreReg(Rn, &success);
9261 if (!success)
9262 return false;
9264 // Read the register value from register Rm.
9265 uint32_t val2 = ReadCoreReg(Rm, &success);
9266 if (!success)
9267 return false;
9269 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
9270 if (!success)
9271 return false;
9272 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
9274 EmulateInstruction::Context context;
9275 context.type = EmulateInstruction::eContextImmediate;
9276 context.SetNoArgs();
9277 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9278 res.carry_out, res.overflow);
9281 // Reverse Subtract with Carry (immediate) subtracts a register value and the
9282 // value of NOT (Carry flag) from an immediate value, and writes the result to
9283 // the destination register. It can optionally update the condition flags based
9284 // on the result.
9285 bool EmulateInstructionARM::EmulateRSCImm(const uint32_t opcode,
9286 const ARMEncoding encoding) {
9287 #if 0
9288 // ARM pseudo code...
9289 if ConditionPassed() then
9290 EncodingSpecificOperations();
9291 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
9292 if d == 15 then
9293 ALUWritePC(result); // setflags is always FALSE here
9294 else
9295 R[d] = result;
9296 if setflags then
9297 APSR.N = result<31>;
9298 APSR.Z = IsZeroBit(result);
9299 APSR.C = carry;
9300 APSR.V = overflow;
9301 #endif
9303 bool success = false;
9305 uint32_t Rd; // the destination register
9306 uint32_t Rn; // the first operand
9307 bool setflags;
9308 uint32_t
9309 imm32; // the immediate value to be added to the value obtained from Rn
9310 switch (encoding) {
9311 case eEncodingA1:
9312 Rd = Bits32(opcode, 15, 12);
9313 Rn = Bits32(opcode, 19, 16);
9314 setflags = BitIsSet(opcode, 20);
9315 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9317 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9318 // instructions;
9319 if (Rd == 15 && setflags)
9320 return EmulateSUBSPcLrEtc(opcode, encoding);
9321 break;
9322 default:
9323 return false;
9325 // Read the register value from the operand register Rn.
9326 uint32_t reg_val = ReadCoreReg(Rn, &success);
9327 if (!success)
9328 return false;
9330 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
9332 EmulateInstruction::Context context;
9333 context.type = EmulateInstruction::eContextImmediate;
9334 context.SetNoArgs();
9336 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9337 res.carry_out, res.overflow);
9340 // Reverse Subtract with Carry (register) subtracts a register value and the
9341 // value of NOT (Carry flag) from an optionally-shifted register value, and
9342 // writes the result to the destination register. It can optionally update the
9343 // condition flags based on the result.
9344 bool EmulateInstructionARM::EmulateRSCReg(const uint32_t opcode,
9345 const ARMEncoding encoding) {
9346 #if 0
9347 // ARM pseudo code...
9348 if ConditionPassed() then
9349 EncodingSpecificOperations();
9350 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9351 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
9352 if d == 15 then
9353 ALUWritePC(result); // setflags is always FALSE here
9354 else
9355 R[d] = result;
9356 if setflags then
9357 APSR.N = result<31>;
9358 APSR.Z = IsZeroBit(result);
9359 APSR.C = carry;
9360 APSR.V = overflow;
9361 #endif
9363 bool success = false;
9365 uint32_t Rd; // the destination register
9366 uint32_t Rn; // the first operand
9367 uint32_t Rm; // the second operand
9368 bool setflags;
9369 ARM_ShifterType shift_t;
9370 uint32_t shift_n; // the shift applied to the value read from Rm
9371 switch (encoding) {
9372 case eEncodingA1:
9373 Rd = Bits32(opcode, 15, 12);
9374 Rn = Bits32(opcode, 19, 16);
9375 Rm = Bits32(opcode, 3, 0);
9376 setflags = BitIsSet(opcode, 20);
9377 shift_n = DecodeImmShiftARM(opcode, shift_t);
9379 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9380 // instructions;
9381 if (Rd == 15 && setflags)
9382 return EmulateSUBSPcLrEtc(opcode, encoding);
9383 break;
9384 default:
9385 return false;
9387 // Read the register value from register Rn.
9388 uint32_t val1 = ReadCoreReg(Rn, &success);
9389 if (!success)
9390 return false;
9392 // Read the register value from register Rm.
9393 uint32_t val2 = ReadCoreReg(Rm, &success);
9394 if (!success)
9395 return false;
9397 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
9398 if (!success)
9399 return false;
9400 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
9402 EmulateInstruction::Context context;
9403 context.type = EmulateInstruction::eContextImmediate;
9404 context.SetNoArgs();
9405 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9406 res.carry_out, res.overflow);
9409 // Subtract with Carry (immediate) subtracts an immediate value and the value
9410 // of
9411 // NOT (Carry flag) from a register value, and writes the result to the
9412 // destination register.
9413 // It can optionally update the condition flags based on the result.
9414 bool EmulateInstructionARM::EmulateSBCImm(const uint32_t opcode,
9415 const ARMEncoding encoding) {
9416 #if 0
9417 // ARM pseudo code...
9418 if ConditionPassed() then
9419 EncodingSpecificOperations();
9420 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
9421 if d == 15 then // Can only occur for ARM encoding
9422 ALUWritePC(result); // setflags is always FALSE here
9423 else
9424 R[d] = result;
9425 if setflags then
9426 APSR.N = result<31>;
9427 APSR.Z = IsZeroBit(result);
9428 APSR.C = carry;
9429 APSR.V = overflow;
9430 #endif
9432 bool success = false;
9434 uint32_t Rd; // the destination register
9435 uint32_t Rn; // the first operand
9436 bool setflags;
9437 uint32_t
9438 imm32; // the immediate value to be added to the value obtained from Rn
9439 switch (encoding) {
9440 case eEncodingT1:
9441 Rd = Bits32(opcode, 11, 8);
9442 Rn = Bits32(opcode, 19, 16);
9443 setflags = BitIsSet(opcode, 20);
9444 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9445 if (BadReg(Rd) || BadReg(Rn))
9446 return false;
9447 break;
9448 case eEncodingA1:
9449 Rd = Bits32(opcode, 15, 12);
9450 Rn = Bits32(opcode, 19, 16);
9451 setflags = BitIsSet(opcode, 20);
9452 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9454 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9455 // instructions;
9456 if (Rd == 15 && setflags)
9457 return EmulateSUBSPcLrEtc(opcode, encoding);
9458 break;
9459 default:
9460 return false;
9462 // Read the register value from the operand register Rn.
9463 uint32_t reg_val = ReadCoreReg(Rn, &success);
9464 if (!success)
9465 return false;
9467 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
9469 EmulateInstruction::Context context;
9470 context.type = EmulateInstruction::eContextImmediate;
9471 context.SetNoArgs();
9473 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9474 res.carry_out, res.overflow);
9477 // Subtract with Carry (register) subtracts an optionally-shifted register
9478 // value and the value of
9479 // NOT (Carry flag) from a register value, and writes the result to the
9480 // destination register.
9481 // It can optionally update the condition flags based on the result.
9482 bool EmulateInstructionARM::EmulateSBCReg(const uint32_t opcode,
9483 const ARMEncoding encoding) {
9484 #if 0
9485 // ARM pseudo code...
9486 if ConditionPassed() then
9487 EncodingSpecificOperations();
9488 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9489 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
9490 if d == 15 then // Can only occur for ARM encoding
9491 ALUWritePC(result); // setflags is always FALSE here
9492 else
9493 R[d] = result;
9494 if setflags then
9495 APSR.N = result<31>;
9496 APSR.Z = IsZeroBit(result);
9497 APSR.C = carry;
9498 APSR.V = overflow;
9499 #endif
9501 bool success = false;
9503 uint32_t Rd; // the destination register
9504 uint32_t Rn; // the first operand
9505 uint32_t Rm; // the second operand
9506 bool setflags;
9507 ARM_ShifterType shift_t;
9508 uint32_t shift_n; // the shift applied to the value read from Rm
9509 switch (encoding) {
9510 case eEncodingT1:
9511 Rd = Rn = Bits32(opcode, 2, 0);
9512 Rm = Bits32(opcode, 5, 3);
9513 setflags = !InITBlock();
9514 shift_t = SRType_LSL;
9515 shift_n = 0;
9516 break;
9517 case eEncodingT2:
9518 Rd = Bits32(opcode, 11, 8);
9519 Rn = Bits32(opcode, 19, 16);
9520 Rm = Bits32(opcode, 3, 0);
9521 setflags = BitIsSet(opcode, 20);
9522 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9523 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
9524 return false;
9525 break;
9526 case eEncodingA1:
9527 Rd = Bits32(opcode, 15, 12);
9528 Rn = Bits32(opcode, 19, 16);
9529 Rm = Bits32(opcode, 3, 0);
9530 setflags = BitIsSet(opcode, 20);
9531 shift_n = DecodeImmShiftARM(opcode, shift_t);
9533 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9534 // instructions;
9535 if (Rd == 15 && setflags)
9536 return EmulateSUBSPcLrEtc(opcode, encoding);
9537 break;
9538 default:
9539 return false;
9541 // Read the register value from register Rn.
9542 uint32_t val1 = ReadCoreReg(Rn, &success);
9543 if (!success)
9544 return false;
9546 // Read the register value from register Rm.
9547 uint32_t val2 = ReadCoreReg(Rm, &success);
9548 if (!success)
9549 return false;
9551 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
9552 if (!success)
9553 return false;
9554 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
9556 EmulateInstruction::Context context;
9557 context.type = EmulateInstruction::eContextImmediate;
9558 context.SetNoArgs();
9559 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9560 res.carry_out, res.overflow);
9563 // This instruction subtracts an immediate value from a register value, and
9564 // writes the result to the destination register. It can optionally update the
9565 // condition flags based on the result.
9566 bool EmulateInstructionARM::EmulateSUBImmThumb(const uint32_t opcode,
9567 const ARMEncoding encoding) {
9568 #if 0
9569 // ARM pseudo code...
9570 if ConditionPassed() then
9571 EncodingSpecificOperations();
9572 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9573 R[d] = result;
9574 if setflags then
9575 APSR.N = result<31>;
9576 APSR.Z = IsZeroBit(result);
9577 APSR.C = carry;
9578 APSR.V = overflow;
9579 #endif
9581 bool success = false;
9583 uint32_t Rd; // the destination register
9584 uint32_t Rn; // the first operand
9585 bool setflags;
9586 uint32_t imm32; // the immediate value to be subtracted from the value
9587 // obtained from Rn
9588 switch (encoding) {
9589 case eEncodingT1:
9590 Rd = Bits32(opcode, 2, 0);
9591 Rn = Bits32(opcode, 5, 3);
9592 setflags = !InITBlock();
9593 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
9594 break;
9595 case eEncodingT2:
9596 Rd = Rn = Bits32(opcode, 10, 8);
9597 setflags = !InITBlock();
9598 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
9599 break;
9600 case eEncodingT3:
9601 Rd = Bits32(opcode, 11, 8);
9602 Rn = Bits32(opcode, 19, 16);
9603 setflags = BitIsSet(opcode, 20);
9604 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9606 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
9607 if (Rd == 15 && setflags)
9608 return EmulateCMPImm(opcode, eEncodingT2);
9610 // if Rn == '1101' then SEE SUB (SP minus immediate);
9611 if (Rn == 13)
9612 return EmulateSUBSPImm(opcode, eEncodingT2);
9614 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
9615 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
9616 return false;
9617 break;
9618 case eEncodingT4:
9619 Rd = Bits32(opcode, 11, 8);
9620 Rn = Bits32(opcode, 19, 16);
9621 setflags = BitIsSet(opcode, 20);
9622 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
9624 // if Rn == '1111' then SEE ADR;
9625 if (Rn == 15)
9626 return EmulateADR(opcode, eEncodingT2);
9628 // if Rn == '1101' then SEE SUB (SP minus immediate);
9629 if (Rn == 13)
9630 return EmulateSUBSPImm(opcode, eEncodingT3);
9632 if (BadReg(Rd))
9633 return false;
9634 break;
9635 default:
9636 return false;
9638 // Read the register value from the operand register Rn.
9639 uint32_t reg_val = ReadCoreReg(Rn, &success);
9640 if (!success)
9641 return false;
9643 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9645 EmulateInstruction::Context context;
9646 context.type = EmulateInstruction::eContextImmediate;
9647 context.SetNoArgs();
9649 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9650 res.carry_out, res.overflow);
9653 // This instruction subtracts an immediate value from a register value, and
9654 // writes the result to the destination register. It can optionally update the
9655 // condition flags based on the result.
9656 bool EmulateInstructionARM::EmulateSUBImmARM(const uint32_t opcode,
9657 const ARMEncoding encoding) {
9658 #if 0
9659 // ARM pseudo code...
9660 if ConditionPassed() then
9661 EncodingSpecificOperations();
9662 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9663 if d == 15 then
9664 ALUWritePC(result); // setflags is always FALSE here
9665 else
9666 R[d] = result;
9667 if setflags then
9668 APSR.N = result<31>;
9669 APSR.Z = IsZeroBit(result);
9670 APSR.C = carry;
9671 APSR.V = overflow;
9672 #endif
9674 bool success = false;
9676 if (ConditionPassed(opcode)) {
9677 uint32_t Rd; // the destination register
9678 uint32_t Rn; // the first operand
9679 bool setflags;
9680 uint32_t imm32; // the immediate value to be subtracted from the value
9681 // obtained from Rn
9682 switch (encoding) {
9683 case eEncodingA1:
9684 Rd = Bits32(opcode, 15, 12);
9685 Rn = Bits32(opcode, 19, 16);
9686 setflags = BitIsSet(opcode, 20);
9687 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9689 // if Rn == '1111' && S == '0' then SEE ADR;
9690 if (Rn == 15 && !setflags)
9691 return EmulateADR(opcode, eEncodingA2);
9693 // if Rn == '1101' then SEE SUB (SP minus immediate);
9694 if (Rn == 13)
9695 return EmulateSUBSPImm(opcode, eEncodingA1);
9697 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9698 // instructions;
9699 if (Rd == 15 && setflags)
9700 return EmulateSUBSPcLrEtc(opcode, encoding);
9701 break;
9702 default:
9703 return false;
9705 // Read the register value from the operand register Rn.
9706 uint32_t reg_val = ReadCoreReg(Rn, &success);
9707 if (!success)
9708 return false;
9710 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9712 EmulateInstruction::Context context;
9713 if (Rd == 13)
9714 context.type = EmulateInstruction::eContextAdjustStackPointer;
9715 else
9716 context.type = EmulateInstruction::eContextRegisterPlusOffset;
9718 std::optional<RegisterInfo> dwarf_reg =
9719 GetRegisterInfo(eRegisterKindDWARF, Rn);
9720 int64_t imm32_signed = imm32;
9721 context.SetRegisterPlusOffset(*dwarf_reg, -imm32_signed);
9723 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9724 res.carry_out, res.overflow))
9725 return false;
9727 return true;
9730 // Test Equivalence (immediate) performs a bitwise exclusive OR operation on a
9731 // register value and an immediate value. It updates the condition flags based
9732 // on the result, and discards the result.
9733 bool EmulateInstructionARM::EmulateTEQImm(const uint32_t opcode,
9734 const ARMEncoding encoding) {
9735 #if 0
9736 // ARM pseudo code...
9737 if ConditionPassed() then
9738 EncodingSpecificOperations();
9739 result = R[n] EOR imm32;
9740 APSR.N = result<31>;
9741 APSR.Z = IsZeroBit(result);
9742 APSR.C = carry;
9743 // APSR.V unchanged
9744 #endif
9746 bool success = false;
9748 if (ConditionPassed(opcode)) {
9749 uint32_t Rn;
9750 uint32_t
9751 imm32; // the immediate value to be ANDed to the value obtained from Rn
9752 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9753 switch (encoding) {
9754 case eEncodingT1:
9755 Rn = Bits32(opcode, 19, 16);
9756 imm32 = ThumbExpandImm_C(
9757 opcode, APSR_C,
9758 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9759 if (BadReg(Rn))
9760 return false;
9761 break;
9762 case eEncodingA1:
9763 Rn = Bits32(opcode, 19, 16);
9764 imm32 =
9765 ARMExpandImm_C(opcode, APSR_C,
9766 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9767 break;
9768 default:
9769 return false;
9772 // Read the first operand.
9773 uint32_t val1 = ReadCoreReg(Rn, &success);
9774 if (!success)
9775 return false;
9777 uint32_t result = val1 ^ imm32;
9779 EmulateInstruction::Context context;
9780 context.type = EmulateInstruction::eContextImmediate;
9781 context.SetNoArgs();
9783 if (!WriteFlags(context, result, carry))
9784 return false;
9786 return true;
9789 // Test Equivalence (register) performs a bitwise exclusive OR operation on a
9790 // register value and an optionally-shifted register value. It updates the
9791 // condition flags based on the result, and discards the result.
9792 bool EmulateInstructionARM::EmulateTEQReg(const uint32_t opcode,
9793 const ARMEncoding encoding) {
9794 #if 0
9795 // ARM pseudo code...
9796 if ConditionPassed() then
9797 EncodingSpecificOperations();
9798 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9799 result = R[n] EOR shifted;
9800 APSR.N = result<31>;
9801 APSR.Z = IsZeroBit(result);
9802 APSR.C = carry;
9803 // APSR.V unchanged
9804 #endif
9806 bool success = false;
9808 if (ConditionPassed(opcode)) {
9809 uint32_t Rn, Rm;
9810 ARM_ShifterType shift_t;
9811 uint32_t shift_n; // the shift applied to the value read from Rm
9812 uint32_t carry;
9813 switch (encoding) {
9814 case eEncodingT1:
9815 Rn = Bits32(opcode, 19, 16);
9816 Rm = Bits32(opcode, 3, 0);
9817 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9818 if (BadReg(Rn) || BadReg(Rm))
9819 return false;
9820 break;
9821 case eEncodingA1:
9822 Rn = Bits32(opcode, 19, 16);
9823 Rm = Bits32(opcode, 3, 0);
9824 shift_n = DecodeImmShiftARM(opcode, shift_t);
9825 break;
9826 default:
9827 return false;
9830 // Read the first operand.
9831 uint32_t val1 = ReadCoreReg(Rn, &success);
9832 if (!success)
9833 return false;
9835 // Read the second operand.
9836 uint32_t val2 = ReadCoreReg(Rm, &success);
9837 if (!success)
9838 return false;
9840 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9841 if (!success)
9842 return false;
9843 uint32_t result = val1 ^ shifted;
9845 EmulateInstruction::Context context;
9846 context.type = EmulateInstruction::eContextImmediate;
9847 context.SetNoArgs();
9849 if (!WriteFlags(context, result, carry))
9850 return false;
9852 return true;
9855 // Test (immediate) performs a bitwise AND operation on a register value and an
9856 // immediate value. It updates the condition flags based on the result, and
9857 // discards the result.
9858 bool EmulateInstructionARM::EmulateTSTImm(const uint32_t opcode,
9859 const ARMEncoding encoding) {
9860 #if 0
9861 // ARM pseudo code...
9862 if ConditionPassed() then
9863 EncodingSpecificOperations();
9864 result = R[n] AND imm32;
9865 APSR.N = result<31>;
9866 APSR.Z = IsZeroBit(result);
9867 APSR.C = carry;
9868 // APSR.V unchanged
9869 #endif
9871 bool success = false;
9873 if (ConditionPassed(opcode)) {
9874 uint32_t Rn;
9875 uint32_t
9876 imm32; // the immediate value to be ANDed to the value obtained from Rn
9877 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9878 switch (encoding) {
9879 case eEncodingT1:
9880 Rn = Bits32(opcode, 19, 16);
9881 imm32 = ThumbExpandImm_C(
9882 opcode, APSR_C,
9883 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9884 if (BadReg(Rn))
9885 return false;
9886 break;
9887 case eEncodingA1:
9888 Rn = Bits32(opcode, 19, 16);
9889 imm32 =
9890 ARMExpandImm_C(opcode, APSR_C,
9891 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9892 break;
9893 default:
9894 return false;
9897 // Read the first operand.
9898 uint32_t val1 = ReadCoreReg(Rn, &success);
9899 if (!success)
9900 return false;
9902 uint32_t result = val1 & imm32;
9904 EmulateInstruction::Context context;
9905 context.type = EmulateInstruction::eContextImmediate;
9906 context.SetNoArgs();
9908 if (!WriteFlags(context, result, carry))
9909 return false;
9911 return true;
9914 // Test (register) performs a bitwise AND operation on a register value and an
9915 // optionally-shifted register value. It updates the condition flags based on
9916 // the result, and discards the result.
9917 bool EmulateInstructionARM::EmulateTSTReg(const uint32_t opcode,
9918 const ARMEncoding encoding) {
9919 #if 0
9920 // ARM pseudo code...
9921 if ConditionPassed() then
9922 EncodingSpecificOperations();
9923 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9924 result = R[n] AND shifted;
9925 APSR.N = result<31>;
9926 APSR.Z = IsZeroBit(result);
9927 APSR.C = carry;
9928 // APSR.V unchanged
9929 #endif
9931 bool success = false;
9933 if (ConditionPassed(opcode)) {
9934 uint32_t Rn, Rm;
9935 ARM_ShifterType shift_t;
9936 uint32_t shift_n; // the shift applied to the value read from Rm
9937 uint32_t carry;
9938 switch (encoding) {
9939 case eEncodingT1:
9940 Rn = Bits32(opcode, 2, 0);
9941 Rm = Bits32(opcode, 5, 3);
9942 shift_t = SRType_LSL;
9943 shift_n = 0;
9944 break;
9945 case eEncodingT2:
9946 Rn = Bits32(opcode, 19, 16);
9947 Rm = Bits32(opcode, 3, 0);
9948 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9949 if (BadReg(Rn) || BadReg(Rm))
9950 return false;
9951 break;
9952 case eEncodingA1:
9953 Rn = Bits32(opcode, 19, 16);
9954 Rm = Bits32(opcode, 3, 0);
9955 shift_n = DecodeImmShiftARM(opcode, shift_t);
9956 break;
9957 default:
9958 return false;
9961 // Read the first operand.
9962 uint32_t val1 = ReadCoreReg(Rn, &success);
9963 if (!success)
9964 return false;
9966 // Read the second operand.
9967 uint32_t val2 = ReadCoreReg(Rm, &success);
9968 if (!success)
9969 return false;
9971 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9972 if (!success)
9973 return false;
9974 uint32_t result = val1 & shifted;
9976 EmulateInstruction::Context context;
9977 context.type = EmulateInstruction::eContextImmediate;
9978 context.SetNoArgs();
9980 if (!WriteFlags(context, result, carry))
9981 return false;
9983 return true;
9986 // A8.6.216 SUB (SP minus register)
9987 bool EmulateInstructionARM::EmulateSUBSPReg(const uint32_t opcode,
9988 const ARMEncoding encoding) {
9989 #if 0
9990 if ConditionPassed() then
9991 EncodingSpecificOperations();
9992 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9993 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');
9994 if d == 15 then // Can only occur for ARM encoding
9995 ALUWritePC(result); // setflags is always FALSE here
9996 else
9997 R[d] = result;
9998 if setflags then
9999 APSR.N = result<31>;
10000 APSR.Z = IsZeroBit(result);
10001 APSR.C = carry;
10002 APSR.V = overflow;
10003 #endif
10005 bool success = false;
10007 if (ConditionPassed(opcode)) {
10008 uint32_t d;
10009 uint32_t m;
10010 bool setflags;
10011 ARM_ShifterType shift_t;
10012 uint32_t shift_n;
10014 switch (encoding) {
10015 case eEncodingT1:
10016 // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
10017 d = Bits32(opcode, 11, 8);
10018 m = Bits32(opcode, 3, 0);
10019 setflags = BitIsSet(opcode, 20);
10021 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
10022 shift_n = DecodeImmShiftThumb(opcode, shift_t);
10024 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then
10025 // UNPREDICTABLE;
10026 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
10027 return false;
10029 // if d == 15 || BadReg(m) then UNPREDICTABLE;
10030 if ((d == 15) || BadReg(m))
10031 return false;
10032 break;
10034 case eEncodingA1:
10035 // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
10036 d = Bits32(opcode, 15, 12);
10037 m = Bits32(opcode, 3, 0);
10038 setflags = BitIsSet(opcode, 20);
10040 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
10041 // instructions;
10042 if (d == 15 && setflags)
10043 EmulateSUBSPcLrEtc(opcode, encoding);
10045 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
10046 shift_n = DecodeImmShiftARM(opcode, shift_t);
10047 break;
10049 default:
10050 return false;
10053 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10054 uint32_t Rm = ReadCoreReg(m, &success);
10055 if (!success)
10056 return false;
10058 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);
10059 if (!success)
10060 return false;
10062 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');
10063 uint32_t sp_val = ReadCoreReg(SP_REG, &success);
10064 if (!success)
10065 return false;
10067 AddWithCarryResult res = AddWithCarry(sp_val, ~shifted, 1);
10069 EmulateInstruction::Context context;
10070 context.type = eContextArithmetic;
10071 std::optional<RegisterInfo> sp_reg =
10072 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);
10073 std::optional<RegisterInfo> dwarf_reg =
10074 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
10075 context.SetRegisterRegisterOperands(*sp_reg, *dwarf_reg);
10077 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags,
10078 res.carry_out, res.overflow))
10079 return false;
10081 return true;
10084 // A8.6.7 ADD (register-shifted register)
10085 bool EmulateInstructionARM::EmulateADDRegShift(const uint32_t opcode,
10086 const ARMEncoding encoding) {
10087 #if 0
10088 if ConditionPassed() then
10089 EncodingSpecificOperations();
10090 shift_n = UInt(R[s]<7:0>);
10091 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10092 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
10093 R[d] = result;
10094 if setflags then
10095 APSR.N = result<31>;
10096 APSR.Z = IsZeroBit(result);
10097 APSR.C = carry;
10098 APSR.V = overflow;
10099 #endif
10101 bool success = false;
10103 if (ConditionPassed(opcode)) {
10104 uint32_t d;
10105 uint32_t n;
10106 uint32_t m;
10107 uint32_t s;
10108 bool setflags;
10109 ARM_ShifterType shift_t;
10111 switch (encoding) {
10112 case eEncodingA1:
10113 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
10114 d = Bits32(opcode, 15, 12);
10115 n = Bits32(opcode, 19, 16);
10116 m = Bits32(opcode, 3, 0);
10117 s = Bits32(opcode, 11, 8);
10119 // setflags = (S == '1'); shift_t = DecodeRegShift(type);
10120 setflags = BitIsSet(opcode, 20);
10121 shift_t = DecodeRegShift(Bits32(opcode, 6, 5));
10123 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
10124 if ((d == 15) || (n == 15) || (m == 15) || (s == 15))
10125 return false;
10126 break;
10128 default:
10129 return false;
10132 // shift_n = UInt(R[s]<7:0>);
10133 uint32_t Rs = ReadCoreReg(s, &success);
10134 if (!success)
10135 return false;
10137 uint32_t shift_n = Bits32(Rs, 7, 0);
10139 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10140 uint32_t Rm = ReadCoreReg(m, &success);
10141 if (!success)
10142 return false;
10144 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);
10145 if (!success)
10146 return false;
10148 // (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
10149 uint32_t Rn = ReadCoreReg(n, &success);
10150 if (!success)
10151 return false;
10153 AddWithCarryResult res = AddWithCarry(Rn, shifted, 0);
10155 // R[d] = result;
10156 EmulateInstruction::Context context;
10157 context.type = eContextArithmetic;
10158 std::optional<RegisterInfo> reg_n =
10159 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
10160 std::optional<RegisterInfo> reg_m =
10161 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
10163 context.SetRegisterRegisterOperands(*reg_n, *reg_m);
10165 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
10166 res.result))
10167 return false;
10169 // if setflags then
10170 // APSR.N = result<31>;
10171 // APSR.Z = IsZeroBit(result);
10172 // APSR.C = carry;
10173 // APSR.V = overflow;
10174 if (setflags)
10175 return WriteFlags(context, res.result, res.carry_out, res.overflow);
10177 return true;
10180 // A8.6.213 SUB (register)
10181 bool EmulateInstructionARM::EmulateSUBReg(const uint32_t opcode,
10182 const ARMEncoding encoding) {
10183 #if 0
10184 if ConditionPassed() then
10185 EncodingSpecificOperations();
10186 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10187 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
10188 if d == 15 then // Can only occur for ARM encoding
10189 ALUWritePC(result); // setflags is always FALSE here
10190 else
10191 R[d] = result;
10192 if setflags then
10193 APSR.N = result<31>;
10194 APSR.Z = IsZeroBit(result);
10195 APSR.C = carry;
10196 APSR.V = overflow;
10197 #endif
10199 bool success = false;
10201 if (ConditionPassed(opcode)) {
10202 uint32_t d;
10203 uint32_t n;
10204 uint32_t m;
10205 bool setflags;
10206 ARM_ShifterType shift_t;
10207 uint32_t shift_n;
10209 switch (encoding) {
10210 case eEncodingT1:
10211 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
10212 d = Bits32(opcode, 2, 0);
10213 n = Bits32(opcode, 5, 3);
10214 m = Bits32(opcode, 8, 6);
10215 setflags = !InITBlock();
10217 // (shift_t, shift_n) = (SRType_LSL, 0);
10218 shift_t = SRType_LSL;
10219 shift_n = 0;
10221 break;
10223 case eEncodingT2:
10224 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S =="1");
10225 d = Bits32(opcode, 11, 8);
10226 n = Bits32(opcode, 19, 16);
10227 m = Bits32(opcode, 3, 0);
10228 setflags = BitIsSet(opcode, 20);
10230 // if Rd == "1111" && S == "1" then SEE CMP (register);
10231 if (d == 15 && setflags == 1)
10232 return EmulateCMPImm(opcode, eEncodingT3);
10234 // if Rn == "1101" then SEE SUB (SP minus register);
10235 if (n == 13)
10236 return EmulateSUBSPReg(opcode, eEncodingT1);
10238 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
10239 shift_n = DecodeImmShiftThumb(opcode, shift_t);
10241 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then
10242 // UNPREDICTABLE;
10243 if ((d == 13) || ((d == 15) && BitIsClear(opcode, 20)) || (n == 15) ||
10244 BadReg(m))
10245 return false;
10247 break;
10249 case eEncodingA1:
10250 // if Rn == '1101' then SEE SUB (SP minus register);
10251 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
10252 d = Bits32(opcode, 15, 12);
10253 n = Bits32(opcode, 19, 16);
10254 m = Bits32(opcode, 3, 0);
10255 setflags = BitIsSet(opcode, 20);
10257 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
10258 // instructions;
10259 if ((d == 15) && setflags)
10260 EmulateSUBSPcLrEtc(opcode, encoding);
10262 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
10263 shift_n = DecodeImmShiftARM(opcode, shift_t);
10265 break;
10267 default:
10268 return false;
10271 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10272 uint32_t Rm = ReadCoreReg(m, &success);
10273 if (!success)
10274 return false;
10276 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);
10277 if (!success)
10278 return false;
10280 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
10281 uint32_t Rn = ReadCoreReg(n, &success);
10282 if (!success)
10283 return false;
10285 AddWithCarryResult res = AddWithCarry(Rn, ~shifted, 1);
10287 // if d == 15 then // Can only occur for ARM encoding ALUWritePC(result);
10288 // // setflags is always FALSE here else
10289 // R[d] = result;
10290 // if setflags then
10291 // APSR.N = result<31>;
10292 // APSR.Z = IsZeroBit(result);
10293 // APSR.C = carry;
10294 // APSR.V = overflow;
10296 EmulateInstruction::Context context;
10297 context.type = eContextArithmetic;
10298 std::optional<RegisterInfo> reg_n =
10299 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
10300 std::optional<RegisterInfo> reg_m =
10301 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
10302 context.SetRegisterRegisterOperands(*reg_n, *reg_m);
10304 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags,
10305 res.carry_out, res.overflow))
10306 return false;
10308 return true;
10311 // A8.6.202 STREX
10312 // Store Register Exclusive calculates an address from a base register value
10313 // and an immediate offset, and stores a word from a register to memory if the
10314 // executing processor has exclusive access to the memory addressed.
10315 bool EmulateInstructionARM::EmulateSTREX(const uint32_t opcode,
10316 const ARMEncoding encoding) {
10317 #if 0
10318 if ConditionPassed() then
10319 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10320 address = R[n] + imm32;
10321 if ExclusiveMonitorsPass(address,4) then
10322 MemA[address,4] = R[t];
10323 R[d] = 0;
10324 else
10325 R[d] = 1;
10326 #endif
10328 bool success = false;
10330 if (ConditionPassed(opcode)) {
10331 uint32_t d;
10332 uint32_t t;
10333 uint32_t n;
10334 uint32_t imm32;
10335 const uint32_t addr_byte_size = GetAddressByteSize();
10337 switch (encoding) {
10338 case eEncodingT1:
10339 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 =
10340 // ZeroExtend(imm8:'00',
10341 // 32);
10342 d = Bits32(opcode, 11, 8);
10343 t = Bits32(opcode, 15, 12);
10344 n = Bits32(opcode, 19, 16);
10345 imm32 = Bits32(opcode, 7, 0) << 2;
10347 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
10348 if (BadReg(d) || BadReg(t) || (n == 15))
10349 return false;
10351 // if d == n || d == t then UNPREDICTABLE;
10352 if ((d == n) || (d == t))
10353 return false;
10355 break;
10357 case eEncodingA1:
10358 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero
10359 // offset
10360 d = Bits32(opcode, 15, 12);
10361 t = Bits32(opcode, 3, 0);
10362 n = Bits32(opcode, 19, 16);
10363 imm32 = 0;
10365 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
10366 if ((d == 15) || (t == 15) || (n == 15))
10367 return false;
10369 // if d == n || d == t then UNPREDICTABLE;
10370 if ((d == n) || (d == t))
10371 return false;
10373 break;
10375 default:
10376 return false;
10379 // address = R[n] + imm32;
10380 uint32_t Rn = ReadCoreReg(n, &success);
10381 if (!success)
10382 return false;
10384 addr_t address = Rn + imm32;
10386 std::optional<RegisterInfo> base_reg =
10387 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
10388 std::optional<RegisterInfo> data_reg =
10389 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
10390 EmulateInstruction::Context context;
10391 context.type = eContextRegisterStore;
10392 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, imm32);
10394 // if ExclusiveMonitorsPass(address,4) then if (ExclusiveMonitorsPass
10395 // (address, addr_byte_size)) -- For now, for the sake of emulation, we
10396 // will say this
10397 // always return
10398 // true.
10399 if (true) {
10400 // MemA[address,4] = R[t];
10401 uint32_t Rt =
10402 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
10403 if (!success)
10404 return false;
10406 if (!MemAWrite(context, address, Rt, addr_byte_size))
10407 return false;
10409 // R[d] = 0;
10410 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 0))
10411 return false;
10413 #if 0 // unreachable because if true
10414 else
10416 // R[d] = 1;
10417 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
10418 return false;
10420 #endif // unreachable because if true
10422 return true;
10425 // A8.6.197 STRB (immediate, ARM)
10426 bool EmulateInstructionARM::EmulateSTRBImmARM(const uint32_t opcode,
10427 const ARMEncoding encoding) {
10428 #if 0
10429 if ConditionPassed() then
10430 EncodingSpecificOperations();
10431 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10432 address = if index then offset_addr else R[n];
10433 MemU[address,1] = R[t]<7:0>;
10434 if wback then R[n] = offset_addr;
10435 #endif
10437 bool success = false;
10439 if (ConditionPassed(opcode)) {
10440 uint32_t t;
10441 uint32_t n;
10442 uint32_t imm32;
10443 bool index;
10444 bool add;
10445 bool wback;
10447 switch (encoding) {
10448 case eEncodingA1:
10449 // if P == '0' && W == '1' then SEE STRBT;
10450 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
10451 t = Bits32(opcode, 15, 12);
10452 n = Bits32(opcode, 19, 16);
10453 imm32 = Bits32(opcode, 11, 0);
10455 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10456 index = BitIsSet(opcode, 24);
10457 add = BitIsSet(opcode, 23);
10458 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10460 // if t == 15 then UNPREDICTABLE;
10461 if (t == 15)
10462 return false;
10464 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
10465 if (wback && ((n == 15) || (n == t)))
10466 return false;
10468 break;
10470 default:
10471 return false;
10474 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10475 uint32_t Rn = ReadCoreReg(n, &success);
10476 if (!success)
10477 return false;
10479 addr_t offset_addr;
10480 if (add)
10481 offset_addr = Rn + imm32;
10482 else
10483 offset_addr = Rn - imm32;
10485 // address = if index then offset_addr else R[n];
10486 addr_t address;
10487 if (index)
10488 address = offset_addr;
10489 else
10490 address = Rn;
10492 // MemU[address,1] = R[t]<7:0>;
10493 uint32_t Rt = ReadCoreReg(t, &success);
10494 if (!success)
10495 return false;
10497 std::optional<RegisterInfo> base_reg =
10498 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
10499 std::optional<RegisterInfo> data_reg =
10500 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
10501 EmulateInstruction::Context context;
10502 context.type = eContextRegisterStore;
10503 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);
10505 if (!MemUWrite(context, address, Bits32(Rt, 7, 0), 1))
10506 return false;
10508 // if wback then R[n] = offset_addr;
10509 if (wback) {
10510 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10511 offset_addr))
10512 return false;
10515 return true;
10518 // A8.6.194 STR (immediate, ARM)
10519 bool EmulateInstructionARM::EmulateSTRImmARM(const uint32_t opcode,
10520 const ARMEncoding encoding) {
10521 #if 0
10522 if ConditionPassed() then
10523 EncodingSpecificOperations();
10524 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10525 address = if index then offset_addr else R[n];
10526 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
10527 if wback then R[n] = offset_addr;
10528 #endif
10530 bool success = false;
10532 if (ConditionPassed(opcode)) {
10533 uint32_t t;
10534 uint32_t n;
10535 uint32_t imm32;
10536 bool index;
10537 bool add;
10538 bool wback;
10540 const uint32_t addr_byte_size = GetAddressByteSize();
10542 switch (encoding) {
10543 case eEncodingA1:
10544 // if P == '0' && W == '1' then SEE STRT;
10545 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 ==
10546 // '000000000100' then SEE PUSH;
10547 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
10548 t = Bits32(opcode, 15, 12);
10549 n = Bits32(opcode, 19, 16);
10550 imm32 = Bits32(opcode, 11, 0);
10552 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10553 index = BitIsSet(opcode, 24);
10554 add = BitIsSet(opcode, 23);
10555 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10557 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
10558 if (wback && ((n == 15) || (n == t)))
10559 return false;
10561 break;
10563 default:
10564 return false;
10567 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10568 uint32_t Rn = ReadCoreReg(n, &success);
10569 if (!success)
10570 return false;
10572 addr_t offset_addr;
10573 if (add)
10574 offset_addr = Rn + imm32;
10575 else
10576 offset_addr = Rn - imm32;
10578 // address = if index then offset_addr else R[n];
10579 addr_t address;
10580 if (index)
10581 address = offset_addr;
10582 else
10583 address = Rn;
10585 std::optional<RegisterInfo> base_reg =
10586 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
10587 std::optional<RegisterInfo> data_reg =
10588 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
10589 EmulateInstruction::Context context;
10590 context.type = eContextRegisterStore;
10591 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);
10593 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
10594 uint32_t Rt = ReadCoreReg(t, &success);
10595 if (!success)
10596 return false;
10598 if (t == 15) {
10599 uint32_t pc_value = ReadCoreReg(PC_REG, &success);
10600 if (!success)
10601 return false;
10603 if (!MemUWrite(context, address, pc_value, addr_byte_size))
10604 return false;
10605 } else {
10606 if (!MemUWrite(context, address, Rt, addr_byte_size))
10607 return false;
10610 // if wback then R[n] = offset_addr;
10611 if (wback) {
10612 context.type = eContextAdjustBaseRegister;
10613 context.SetImmediate(offset_addr);
10615 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10616 offset_addr))
10617 return false;
10620 return true;
10623 // A8.6.66 LDRD (immediate)
10624 // Load Register Dual (immediate) calculates an address from a base register
10625 // value and an immediate offset, loads two words from memory, and writes them
10626 // to two registers. It can use offset, post-indexed, or pre-indexed
10627 // addressing.
10628 bool EmulateInstructionARM::EmulateLDRDImmediate(const uint32_t opcode,
10629 const ARMEncoding encoding) {
10630 #if 0
10631 if ConditionPassed() then
10632 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10633 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10634 address = if index then offset_addr else R[n];
10635 R[t] = MemA[address,4];
10636 R[t2] = MemA[address+4,4];
10637 if wback then R[n] = offset_addr;
10638 #endif
10640 bool success = false;
10642 if (ConditionPassed(opcode)) {
10643 uint32_t t;
10644 uint32_t t2;
10645 uint32_t n;
10646 uint32_t imm32;
10647 bool index;
10648 bool add;
10649 bool wback;
10651 switch (encoding) {
10652 case eEncodingT1:
10653 // if P == '0' && W == '0' then SEE 'Related encodings';
10654 // if Rn == '1111' then SEE LDRD (literal);
10655 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 =
10656 // ZeroExtend(imm8:'00', 32);
10657 t = Bits32(opcode, 15, 12);
10658 t2 = Bits32(opcode, 11, 8);
10659 n = Bits32(opcode, 19, 16);
10660 imm32 = Bits32(opcode, 7, 0) << 2;
10662 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
10663 index = BitIsSet(opcode, 24);
10664 add = BitIsSet(opcode, 23);
10665 wback = BitIsSet(opcode, 21);
10667 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10668 if (wback && ((n == t) || (n == t2)))
10669 return false;
10671 // if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
10672 if (BadReg(t) || BadReg(t2) || (t == t2))
10673 return false;
10675 break;
10677 case eEncodingA1:
10678 // if Rn == '1111' then SEE LDRD (literal);
10679 // if Rt<0> == '1' then UNPREDICTABLE;
10680 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L,
10681 // 32);
10682 t = Bits32(opcode, 15, 12);
10683 if (BitIsSet(t, 0))
10684 return false;
10685 t2 = t + 1;
10686 n = Bits32(opcode, 19, 16);
10687 imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0);
10689 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10690 index = BitIsSet(opcode, 24);
10691 add = BitIsSet(opcode, 23);
10692 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10694 // if P == '0' && W == '1' then UNPREDICTABLE;
10695 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
10696 return false;
10698 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10699 if (wback && ((n == t) || (n == t2)))
10700 return false;
10702 // if t2 == 15 then UNPREDICTABLE;
10703 if (t2 == 15)
10704 return false;
10706 break;
10708 default:
10709 return false;
10712 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10713 uint32_t Rn = ReadCoreReg(n, &success);
10714 if (!success)
10715 return false;
10717 addr_t offset_addr;
10718 if (add)
10719 offset_addr = Rn + imm32;
10720 else
10721 offset_addr = Rn - imm32;
10723 // address = if index then offset_addr else R[n];
10724 addr_t address;
10725 if (index)
10726 address = offset_addr;
10727 else
10728 address = Rn;
10730 // R[t] = MemA[address,4];
10732 EmulateInstruction::Context context;
10733 if (n == 13)
10734 context.type = eContextPopRegisterOffStack;
10735 else
10736 context.type = eContextRegisterLoad;
10737 context.SetAddress(address);
10739 const uint32_t addr_byte_size = GetAddressByteSize();
10740 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
10741 if (!success)
10742 return false;
10744 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
10745 return false;
10747 // R[t2] = MemA[address+4,4];
10748 context.SetAddress(address + 4);
10749 data = MemARead(context, address + 4, addr_byte_size, 0, &success);
10750 if (!success)
10751 return false;
10753 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2,
10754 data))
10755 return false;
10757 // if wback then R[n] = offset_addr;
10758 if (wback) {
10759 context.type = eContextAdjustBaseRegister;
10760 context.SetAddress(offset_addr);
10762 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10763 offset_addr))
10764 return false;
10767 return true;
10770 // A8.6.68 LDRD (register)
10771 // Load Register Dual (register) calculates an address from a base register
10772 // value and a register offset, loads two words from memory, and writes them to
10773 // two registers. It can use offset, post-indexed or pre-indexed addressing.
10774 bool EmulateInstructionARM::EmulateLDRDRegister(const uint32_t opcode,
10775 const ARMEncoding encoding) {
10776 #if 0
10777 if ConditionPassed() then
10778 EncodingSpecificOperations();
10779 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10780 address = if index then offset_addr else R[n];
10781 R[t] = MemA[address,4];
10782 R[t2] = MemA[address+4,4];
10783 if wback then R[n] = offset_addr;
10784 #endif
10786 bool success = false;
10788 if (ConditionPassed(opcode)) {
10789 uint32_t t;
10790 uint32_t t2;
10791 uint32_t n;
10792 uint32_t m;
10793 bool index;
10794 bool add;
10795 bool wback;
10797 switch (encoding) {
10798 case eEncodingA1:
10799 // if Rt<0> == '1' then UNPREDICTABLE;
10800 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10801 t = Bits32(opcode, 15, 12);
10802 if (BitIsSet(t, 0))
10803 return false;
10804 t2 = t + 1;
10805 n = Bits32(opcode, 19, 16);
10806 m = Bits32(opcode, 3, 0);
10808 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10809 index = BitIsSet(opcode, 24);
10810 add = BitIsSet(opcode, 23);
10811 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10813 // if P == '0' && W == '1' then UNPREDICTABLE;
10814 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
10815 return false;
10817 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10818 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
10819 return false;
10821 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10822 if (wback && ((n == 15) || (n == t) || (n == t2)))
10823 return false;
10825 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10826 if ((ArchVersion() < 6) && wback && (m == n))
10827 return false;
10828 break;
10830 default:
10831 return false;
10834 uint32_t Rn = ReadCoreReg(n, &success);
10835 if (!success)
10836 return false;
10838 uint32_t Rm = ReadCoreReg(m, &success);
10839 if (!success)
10840 return false;
10842 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10843 addr_t offset_addr;
10844 if (add)
10845 offset_addr = Rn + Rm;
10846 else
10847 offset_addr = Rn - Rm;
10849 // address = if index then offset_addr else R[n];
10850 addr_t address;
10851 if (index)
10852 address = offset_addr;
10853 else
10854 address = Rn;
10856 EmulateInstruction::Context context;
10857 if (n == 13)
10858 context.type = eContextPopRegisterOffStack;
10859 else
10860 context.type = eContextRegisterLoad;
10861 context.SetAddress(address);
10863 // R[t] = MemA[address,4];
10864 const uint32_t addr_byte_size = GetAddressByteSize();
10865 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
10866 if (!success)
10867 return false;
10869 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
10870 return false;
10872 // R[t2] = MemA[address+4,4];
10874 data = MemARead(context, address + 4, addr_byte_size, 0, &success);
10875 if (!success)
10876 return false;
10878 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2,
10879 data))
10880 return false;
10882 // if wback then R[n] = offset_addr;
10883 if (wback) {
10884 context.type = eContextAdjustBaseRegister;
10885 context.SetAddress(offset_addr);
10887 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10888 offset_addr))
10889 return false;
10892 return true;
10895 // A8.6.200 STRD (immediate)
10896 // Store Register Dual (immediate) calculates an address from a base register
10897 // value and an immediate offset, and stores two words from two registers to
10898 // memory. It can use offset, post-indexed, or pre-indexed addressing.
10899 bool EmulateInstructionARM::EmulateSTRDImm(const uint32_t opcode,
10900 const ARMEncoding encoding) {
10901 #if 0
10902 if ConditionPassed() then
10903 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10904 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10905 address = if index then offset_addr else R[n];
10906 MemA[address,4] = R[t];
10907 MemA[address+4,4] = R[t2];
10908 if wback then R[n] = offset_addr;
10909 #endif
10911 bool success = false;
10913 if (ConditionPassed(opcode)) {
10914 uint32_t t;
10915 uint32_t t2;
10916 uint32_t n;
10917 uint32_t imm32;
10918 bool index;
10919 bool add;
10920 bool wback;
10922 switch (encoding) {
10923 case eEncodingT1:
10924 // if P == '0' && W == '0' then SEE 'Related encodings';
10925 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 =
10926 // ZeroExtend(imm8:'00', 32);
10927 t = Bits32(opcode, 15, 12);
10928 t2 = Bits32(opcode, 11, 8);
10929 n = Bits32(opcode, 19, 16);
10930 imm32 = Bits32(opcode, 7, 0) << 2;
10932 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
10933 index = BitIsSet(opcode, 24);
10934 add = BitIsSet(opcode, 23);
10935 wback = BitIsSet(opcode, 21);
10937 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10938 if (wback && ((n == t) || (n == t2)))
10939 return false;
10941 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
10942 if ((n == 15) || BadReg(t) || BadReg(t2))
10943 return false;
10945 break;
10947 case eEncodingA1:
10948 // if Rt<0> == '1' then UNPREDICTABLE;
10949 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L,
10950 // 32);
10951 t = Bits32(opcode, 15, 12);
10952 if (BitIsSet(t, 0))
10953 return false;
10955 t2 = t + 1;
10956 n = Bits32(opcode, 19, 16);
10957 imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0);
10959 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10960 index = BitIsSet(opcode, 24);
10961 add = BitIsSet(opcode, 23);
10962 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10964 // if P == '0' && W == '1' then UNPREDICTABLE;
10965 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
10966 return false;
10968 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10969 if (wback && ((n == 15) || (n == t) || (n == t2)))
10970 return false;
10972 // if t2 == 15 then UNPREDICTABLE;
10973 if (t2 == 15)
10974 return false;
10976 break;
10978 default:
10979 return false;
10982 std::optional<RegisterInfo> base_reg =
10983 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
10985 uint32_t Rn = ReadCoreReg(n, &success);
10986 if (!success)
10987 return false;
10989 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10990 addr_t offset_addr;
10991 if (add)
10992 offset_addr = Rn + imm32;
10993 else
10994 offset_addr = Rn - imm32;
10996 // address = if index then offset_addr else R[n];
10997 addr_t address;
10998 if (index)
10999 address = offset_addr;
11000 else
11001 address = Rn;
11003 // MemA[address,4] = R[t];
11004 std::optional<RegisterInfo> data_reg =
11005 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
11007 uint32_t data = ReadCoreReg(t, &success);
11008 if (!success)
11009 return false;
11011 EmulateInstruction::Context context;
11012 if (n == 13)
11013 context.type = eContextPushRegisterOnStack;
11014 else
11015 context.type = eContextRegisterStore;
11016 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);
11018 const uint32_t addr_byte_size = GetAddressByteSize();
11020 if (!MemAWrite(context, address, data, addr_byte_size))
11021 return false;
11023 // MemA[address+4,4] = R[t2];
11024 data_reg = GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2);
11025 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
11026 (address + 4) - Rn);
11028 data = ReadCoreReg(t2, &success);
11029 if (!success)
11030 return false;
11032 if (!MemAWrite(context, address + 4, data, addr_byte_size))
11033 return false;
11035 // if wback then R[n] = offset_addr;
11036 if (wback) {
11037 if (n == 13)
11038 context.type = eContextAdjustStackPointer;
11039 else
11040 context.type = eContextAdjustBaseRegister;
11041 context.SetAddress(offset_addr);
11043 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11044 offset_addr))
11045 return false;
11048 return true;
11051 // A8.6.201 STRD (register)
11052 bool EmulateInstructionARM::EmulateSTRDReg(const uint32_t opcode,
11053 const ARMEncoding encoding) {
11054 #if 0
11055 if ConditionPassed() then
11056 EncodingSpecificOperations();
11057 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
11058 address = if index then offset_addr else R[n];
11059 MemA[address,4] = R[t];
11060 MemA[address+4,4] = R[t2];
11061 if wback then R[n] = offset_addr;
11062 #endif
11064 bool success = false;
11066 if (ConditionPassed(opcode)) {
11067 uint32_t t;
11068 uint32_t t2;
11069 uint32_t n;
11070 uint32_t m;
11071 bool index;
11072 bool add;
11073 bool wback;
11075 switch (encoding) {
11076 case eEncodingA1:
11077 // if Rt<0> == '1' then UNPREDICTABLE;
11078 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
11079 t = Bits32(opcode, 15, 12);
11080 if (BitIsSet(t, 0))
11081 return false;
11083 t2 = t + 1;
11084 n = Bits32(opcode, 19, 16);
11085 m = Bits32(opcode, 3, 0);
11087 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
11088 index = BitIsSet(opcode, 24);
11089 add = BitIsSet(opcode, 23);
11090 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
11092 // if P == '0' && W == '1' then UNPREDICTABLE;
11093 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
11094 return false;
11096 // if t2 == 15 || m == 15 then UNPREDICTABLE;
11097 if ((t2 == 15) || (m == 15))
11098 return false;
11100 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
11101 if (wback && ((n == 15) || (n == t) || (n == t2)))
11102 return false;
11104 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
11105 if ((ArchVersion() < 6) && wback && (m == n))
11106 return false;
11108 break;
11110 default:
11111 return false;
11114 uint32_t Rn = ReadCoreReg(n, &success);
11115 if (!success)
11116 return false;
11118 uint32_t Rm = ReadCoreReg(m, &success);
11119 if (!success)
11120 return false;
11122 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
11123 addr_t offset_addr;
11124 if (add)
11125 offset_addr = Rn + Rm;
11126 else
11127 offset_addr = Rn - Rm;
11129 // address = if index then offset_addr else R[n];
11130 addr_t address;
11131 if (index)
11132 address = offset_addr;
11133 else
11134 address = Rn;
11135 // MemA[address,4] = R[t];
11136 uint32_t Rt = ReadCoreReg(t, &success);
11137 if (!success)
11138 return false;
11140 EmulateInstruction::Context context;
11141 if (t == 13)
11142 context.type = eContextPushRegisterOnStack;
11143 else
11144 context.type = eContextRegisterStore;
11146 std::optional<RegisterInfo> base_reg =
11147 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
11148 std::optional<RegisterInfo> offset_reg =
11149 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
11150 std::optional<RegisterInfo> data_reg =
11151 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
11152 context.SetRegisterToRegisterPlusIndirectOffset(*base_reg, *offset_reg,
11153 *data_reg);
11155 const uint32_t addr_byte_size = GetAddressByteSize();
11157 if (!MemAWrite(context, address, Rt, addr_byte_size))
11158 return false;
11160 // MemA[address+4,4] = R[t2];
11161 uint32_t Rt2 = ReadCoreReg(t2, &success);
11162 if (!success)
11163 return false;
11165 data_reg = GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2);
11167 context.SetRegisterToRegisterPlusIndirectOffset(*base_reg, *offset_reg,
11168 *data_reg);
11170 if (!MemAWrite(context, address + 4, Rt2, addr_byte_size))
11171 return false;
11173 // if wback then R[n] = offset_addr;
11174 if (wback) {
11175 context.type = eContextAdjustBaseRegister;
11176 context.SetAddress(offset_addr);
11178 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11179 offset_addr))
11180 return false;
11183 return true;
11186 // A8.6.319 VLDM
11187 // Vector Load Multiple loads multiple extension registers from consecutive
11188 // memory locations using an address from an ARM core register.
11189 bool EmulateInstructionARM::EmulateVLDM(const uint32_t opcode,
11190 const ARMEncoding encoding) {
11191 #if 0
11192 if ConditionPassed() then
11193 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11194 address = if add then R[n] else R[n]-imm32;
11195 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11196 for r = 0 to regs-1
11197 if single_regs then
11198 S[d+r] = MemA[address,4]; address = address+4;
11199 else
11200 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
11201 // Combine the word-aligned words in the correct order for
11202 // current endianness.
11203 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
11204 #endif
11206 bool success = false;
11208 if (ConditionPassed(opcode)) {
11209 bool single_regs;
11210 bool add;
11211 bool wback;
11212 uint32_t d;
11213 uint32_t n;
11214 uint32_t imm32;
11215 uint32_t regs;
11217 switch (encoding) {
11218 case eEncodingT1:
11219 case eEncodingA1:
11220 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11221 // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;
11222 // if P == '1' && W == '0' then SEE VLDR;
11223 // if P == U && W == '1' then UNDEFINED;
11224 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11225 return false;
11227 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11228 // !), 101 (DB with !)
11229 // single_regs = FALSE; add = (U == '1'); wback = (W == '1');
11230 single_regs = false;
11231 add = BitIsSet(opcode, 23);
11232 wback = BitIsSet(opcode, 21);
11234 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
11235 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11236 n = Bits32(opcode, 19, 16);
11237 imm32 = Bits32(opcode, 7, 0) << 2;
11239 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FLDMX'.
11240 regs = Bits32(opcode, 7, 0) / 2;
11242 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11243 // UNPREDICTABLE;
11244 if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
11245 return false;
11247 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
11248 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
11249 return false;
11251 break;
11253 case eEncodingT2:
11254 case eEncodingA2:
11255 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11256 // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;
11257 // if P == '1' && W == '0' then SEE VLDR;
11258 // if P == U && W == '1' then UNDEFINED;
11259 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11260 return false;
11262 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11263 // !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W
11264 // == '1'); d =
11265 // UInt(Vd:D); n = UInt(Rn);
11266 single_regs = true;
11267 add = BitIsSet(opcode, 23);
11268 wback = BitIsSet(opcode, 21);
11269 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11270 n = Bits32(opcode, 19, 16);
11272 // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
11273 imm32 = Bits32(opcode, 7, 0) << 2;
11274 regs = Bits32(opcode, 7, 0);
11276 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11277 // UNPREDICTABLE;
11278 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11279 return false;
11281 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
11282 if ((regs == 0) || ((d + regs) > 32))
11283 return false;
11284 break;
11286 default:
11287 return false;
11290 uint32_t Rn = ReadCoreReg(n, &success);
11291 if (!success)
11292 return false;
11294 // address = if add then R[n] else R[n]-imm32;
11295 addr_t address;
11296 if (add)
11297 address = Rn;
11298 else
11299 address = Rn - imm32;
11301 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11302 EmulateInstruction::Context context;
11304 if (wback) {
11305 uint32_t value;
11306 if (add)
11307 value = Rn + imm32;
11308 else
11309 value = Rn - imm32;
11311 context.type = eContextAdjustBaseRegister;
11312 context.SetImmediateSigned(value - Rn);
11313 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11314 value))
11315 return false;
11318 const uint32_t addr_byte_size = GetAddressByteSize();
11319 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
11321 context.type = eContextRegisterLoad;
11323 std::optional<RegisterInfo> base_reg =
11324 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
11326 // for r = 0 to regs-1
11327 for (uint32_t r = 0; r < regs; ++r) {
11328 if (single_regs) {
11329 // S[d+r] = MemA[address,4]; address = address+4;
11330 context.SetRegisterPlusOffset(*base_reg, address - Rn);
11332 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
11333 if (!success)
11334 return false;
11336 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
11337 start_reg + d + r, data))
11338 return false;
11340 address = address + 4;
11341 } else {
11342 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address =
11343 // address+8;
11344 context.SetRegisterPlusOffset(*base_reg, address - Rn);
11345 uint32_t word1 =
11346 MemARead(context, address, addr_byte_size, 0, &success);
11347 if (!success)
11348 return false;
11350 context.SetRegisterPlusOffset(*base_reg, (address + 4) - Rn);
11351 uint32_t word2 =
11352 MemARead(context, address + 4, addr_byte_size, 0, &success);
11353 if (!success)
11354 return false;
11356 address = address + 8;
11357 // // Combine the word-aligned words in the correct order for current
11358 // endianness.
11359 // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
11360 uint64_t data;
11361 if (GetByteOrder() == eByteOrderBig) {
11362 data = word1;
11363 data = (data << 32) | word2;
11364 } else {
11365 data = word2;
11366 data = (data << 32) | word1;
11369 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
11370 start_reg + d + r, data))
11371 return false;
11375 return true;
11378 // A8.6.399 VSTM
11379 // Vector Store Multiple stores multiple extension registers to consecutive
11380 // memory locations using an address from an
11381 // ARM core register.
11382 bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode,
11383 const ARMEncoding encoding) {
11384 #if 0
11385 if ConditionPassed() then
11386 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11387 address = if add then R[n] else R[n]-imm32;
11388 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11389 for r = 0 to regs-1
11390 if single_regs then
11391 MemA[address,4] = S[d+r]; address = address+4;
11392 else
11393 // Store as two word-aligned words in the correct order for
11394 // current endianness.
11395 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
11396 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
11397 address = address+8;
11398 #endif
11400 bool success = false;
11402 if (ConditionPassed(opcode)) {
11403 bool single_regs;
11404 bool add;
11405 bool wback;
11406 uint32_t d;
11407 uint32_t n;
11408 uint32_t imm32;
11409 uint32_t regs;
11411 switch (encoding) {
11412 case eEncodingT1:
11413 case eEncodingA1:
11414 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11415 // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;
11416 // if P == '1' && W == '0' then SEE VSTR;
11417 // if P == U && W == '1' then UNDEFINED;
11418 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11419 return false;
11421 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11422 // !), 101 (DB with !)
11423 // single_regs = FALSE; add = (U == '1'); wback = (W == '1');
11424 single_regs = false;
11425 add = BitIsSet(opcode, 23);
11426 wback = BitIsSet(opcode, 21);
11428 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
11429 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11430 n = Bits32(opcode, 19, 16);
11431 imm32 = Bits32(opcode, 7, 0) << 2;
11433 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FSTMX'.
11434 regs = Bits32(opcode, 7, 0) / 2;
11436 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11437 // UNPREDICTABLE;
11438 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11439 return false;
11441 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
11442 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
11443 return false;
11445 break;
11447 case eEncodingT2:
11448 case eEncodingA2:
11449 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11450 // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;
11451 // if P == '1' && W == '0' then SEE VSTR;
11452 // if P == U && W == '1' then UNDEFINED;
11453 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11454 return false;
11456 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11457 // !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W
11458 // == '1'); d =
11459 // UInt(Vd:D); n = UInt(Rn);
11460 single_regs = true;
11461 add = BitIsSet(opcode, 23);
11462 wback = BitIsSet(opcode, 21);
11463 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11464 n = Bits32(opcode, 19, 16);
11466 // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
11467 imm32 = Bits32(opcode, 7, 0) << 2;
11468 regs = Bits32(opcode, 7, 0);
11470 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11471 // UNPREDICTABLE;
11472 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11473 return false;
11475 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
11476 if ((regs == 0) || ((d + regs) > 32))
11477 return false;
11479 break;
11481 default:
11482 return false;
11485 std::optional<RegisterInfo> base_reg =
11486 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
11488 uint32_t Rn = ReadCoreReg(n, &success);
11489 if (!success)
11490 return false;
11492 // address = if add then R[n] else R[n]-imm32;
11493 addr_t address;
11494 if (add)
11495 address = Rn;
11496 else
11497 address = Rn - imm32;
11499 EmulateInstruction::Context context;
11500 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11501 if (wback) {
11502 uint32_t value;
11503 if (add)
11504 value = Rn + imm32;
11505 else
11506 value = Rn - imm32;
11508 context.type = eContextAdjustBaseRegister;
11509 context.SetRegisterPlusOffset(*base_reg, value - Rn);
11511 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11512 value))
11513 return false;
11516 const uint32_t addr_byte_size = GetAddressByteSize();
11517 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
11519 context.type = eContextRegisterStore;
11520 // for r = 0 to regs-1
11521 for (uint32_t r = 0; r < regs; ++r) {
11523 if (single_regs) {
11524 // MemA[address,4] = S[d+r]; address = address+4;
11525 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF,
11526 start_reg + d + r, 0, &success);
11527 if (!success)
11528 return false;
11530 std::optional<RegisterInfo> data_reg =
11531 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r);
11532 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
11533 address - Rn);
11534 if (!MemAWrite(context, address, data, addr_byte_size))
11535 return false;
11537 address = address + 4;
11538 } else {
11539 // // Store as two word-aligned words in the correct order for current
11540 // endianness. MemA[address,4] = if BigEndian() then D[d+r]<63:32> else
11541 // D[d+r]<31:0>;
11542 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else
11543 // D[d+r]<63:32>;
11544 uint64_t data = ReadRegisterUnsigned(eRegisterKindDWARF,
11545 start_reg + d + r, 0, &success);
11546 if (!success)
11547 return false;
11549 std::optional<RegisterInfo> data_reg =
11550 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r);
11552 if (GetByteOrder() == eByteOrderBig) {
11553 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
11554 address - Rn);
11555 if (!MemAWrite(context, address, Bits64(data, 63, 32),
11556 addr_byte_size))
11557 return false;
11559 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
11560 (address + 4) - Rn);
11561 if (!MemAWrite(context, address + 4, Bits64(data, 31, 0),
11562 addr_byte_size))
11563 return false;
11564 } else {
11565 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
11566 address - Rn);
11567 if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size))
11568 return false;
11570 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
11571 (address + 4) - Rn);
11572 if (!MemAWrite(context, address + 4, Bits64(data, 63, 32),
11573 addr_byte_size))
11574 return false;
11576 // address = address+8;
11577 address = address + 8;
11581 return true;
11584 // A8.6.320
11585 // This instruction loads a single extension register from memory, using an
11586 // address from an ARM core register, with an optional offset.
11587 bool EmulateInstructionARM::EmulateVLDR(const uint32_t opcode,
11588 ARMEncoding encoding) {
11589 #if 0
11590 if ConditionPassed() then
11591 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11592 base = if n == 15 then Align(PC,4) else R[n];
11593 address = if add then (base + imm32) else (base - imm32);
11594 if single_reg then
11595 S[d] = MemA[address,4];
11596 else
11597 word1 = MemA[address,4]; word2 = MemA[address+4,4];
11598 // Combine the word-aligned words in the correct order for current
11599 // endianness.
11600 D[d] = if BigEndian() then word1:word2 else word2:word1;
11601 #endif
11603 bool success = false;
11605 if (ConditionPassed(opcode)) {
11606 bool single_reg;
11607 bool add;
11608 uint32_t imm32;
11609 uint32_t d;
11610 uint32_t n;
11612 switch (encoding) {
11613 case eEncodingT1:
11614 case eEncodingA1:
11615 // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00',
11616 // 32);
11617 single_reg = false;
11618 add = BitIsSet(opcode, 23);
11619 imm32 = Bits32(opcode, 7, 0) << 2;
11621 // d = UInt(D:Vd); n = UInt(Rn);
11622 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11623 n = Bits32(opcode, 19, 16);
11625 break;
11627 case eEncodingT2:
11628 case eEncodingA2:
11629 // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
11630 single_reg = true;
11631 add = BitIsSet(opcode, 23);
11632 imm32 = Bits32(opcode, 7, 0) << 2;
11634 // d = UInt(Vd:D); n = UInt(Rn);
11635 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11636 n = Bits32(opcode, 19, 16);
11638 break;
11640 default:
11641 return false;
11643 std::optional<RegisterInfo> base_reg =
11644 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
11646 uint32_t Rn = ReadCoreReg(n, &success);
11647 if (!success)
11648 return false;
11650 // base = if n == 15 then Align(PC,4) else R[n];
11651 uint32_t base;
11652 if (n == 15)
11653 base = AlignPC(Rn);
11654 else
11655 base = Rn;
11657 // address = if add then (base + imm32) else (base - imm32);
11658 addr_t address;
11659 if (add)
11660 address = base + imm32;
11661 else
11662 address = base - imm32;
11664 const uint32_t addr_byte_size = GetAddressByteSize();
11665 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11667 EmulateInstruction::Context context;
11668 context.type = eContextRegisterLoad;
11669 context.SetRegisterPlusOffset(*base_reg, address - base);
11671 if (single_reg) {
11672 // S[d] = MemA[address,4];
11673 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
11674 if (!success)
11675 return false;
11677 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d,
11678 data))
11679 return false;
11680 } else {
11681 // word1 = MemA[address,4]; word2 = MemA[address+4,4];
11682 uint32_t word1 = MemARead(context, address, addr_byte_size, 0, &success);
11683 if (!success)
11684 return false;
11686 context.SetRegisterPlusOffset(*base_reg, (address + 4) - base);
11687 uint32_t word2 =
11688 MemARead(context, address + 4, addr_byte_size, 0, &success);
11689 if (!success)
11690 return false;
11691 // // Combine the word-aligned words in the correct order for current
11692 // endianness.
11693 // D[d] = if BigEndian() then word1:word2 else word2:word1;
11694 uint64_t data64;
11695 if (GetByteOrder() == eByteOrderBig) {
11696 data64 = word1;
11697 data64 = (data64 << 32) | word2;
11698 } else {
11699 data64 = word2;
11700 data64 = (data64 << 32) | word1;
11703 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d,
11704 data64))
11705 return false;
11708 return true;
11711 // A8.6.400 VSTR
11712 // This instruction stores a signle extension register to memory, using an
11713 // address from an ARM core register, with an optional offset.
11714 bool EmulateInstructionARM::EmulateVSTR(const uint32_t opcode,
11715 ARMEncoding encoding) {
11716 #if 0
11717 if ConditionPassed() then
11718 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11719 address = if add then (R[n] + imm32) else (R[n] - imm32);
11720 if single_reg then
11721 MemA[address,4] = S[d];
11722 else
11723 // Store as two word-aligned words in the correct order for current
11724 // endianness.
11725 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11726 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11727 #endif
11729 bool success = false;
11731 if (ConditionPassed(opcode)) {
11732 bool single_reg;
11733 bool add;
11734 uint32_t imm32;
11735 uint32_t d;
11736 uint32_t n;
11738 switch (encoding) {
11739 case eEncodingT1:
11740 case eEncodingA1:
11741 // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00',
11742 // 32);
11743 single_reg = false;
11744 add = BitIsSet(opcode, 23);
11745 imm32 = Bits32(opcode, 7, 0) << 2;
11747 // d = UInt(D:Vd); n = UInt(Rn);
11748 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11749 n = Bits32(opcode, 19, 16);
11751 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11752 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11753 return false;
11755 break;
11757 case eEncodingT2:
11758 case eEncodingA2:
11759 // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
11760 single_reg = true;
11761 add = BitIsSet(opcode, 23);
11762 imm32 = Bits32(opcode, 7, 0) << 2;
11764 // d = UInt(Vd:D); n = UInt(Rn);
11765 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11766 n = Bits32(opcode, 19, 16);
11768 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11769 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11770 return false;
11772 break;
11774 default:
11775 return false;
11778 uint32_t Rn = ReadCoreReg(n, &success);
11779 if (!success)
11780 return false;
11782 // address = if add then (R[n] + imm32) else (R[n] - imm32);
11783 addr_t address;
11784 if (add)
11785 address = Rn + imm32;
11786 else
11787 address = Rn - imm32;
11789 const uint32_t addr_byte_size = GetAddressByteSize();
11790 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11792 std::optional<RegisterInfo> base_reg =
11793 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
11794 std::optional<RegisterInfo> data_reg =
11795 GetRegisterInfo(eRegisterKindDWARF, start_reg + d);
11796 EmulateInstruction::Context context;
11797 context.type = eContextRegisterStore;
11798 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);
11800 if (single_reg) {
11801 // MemA[address,4] = S[d];
11802 uint32_t data =
11803 ReadRegisterUnsigned(eRegisterKindDWARF, start_reg + d, 0, &success);
11804 if (!success)
11805 return false;
11807 if (!MemAWrite(context, address, data, addr_byte_size))
11808 return false;
11809 } else {
11810 // // Store as two word-aligned words in the correct order for current
11811 // endianness.
11812 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11813 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11814 uint64_t data =
11815 ReadRegisterUnsigned(eRegisterKindDWARF, start_reg + d, 0, &success);
11816 if (!success)
11817 return false;
11819 if (GetByteOrder() == eByteOrderBig) {
11820 if (!MemAWrite(context, address, Bits64(data, 63, 32), addr_byte_size))
11821 return false;
11823 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
11824 (address + 4) - Rn);
11825 if (!MemAWrite(context, address + 4, Bits64(data, 31, 0),
11826 addr_byte_size))
11827 return false;
11828 } else {
11829 if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size))
11830 return false;
11832 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
11833 (address + 4) - Rn);
11834 if (!MemAWrite(context, address + 4, Bits64(data, 63, 32),
11835 addr_byte_size))
11836 return false;
11840 return true;
11843 // A8.6.307 VLDI1 (multiple single elements) This instruction loads elements
11844 // from memory into one, two, three or four registers, without de-interleaving.
11845 // Every element of each register is loaded.
11846 bool EmulateInstructionARM::EmulateVLD1Multiple(const uint32_t opcode,
11847 ARMEncoding encoding) {
11848 #if 0
11849 if ConditionPassed() then
11850 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11851 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11852 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11853 for r = 0 to regs-1
11854 for e = 0 to elements-1
11855 Elem[D[d+r],e,esize] = MemU[address,ebytes];
11856 address = address + ebytes;
11857 #endif
11859 bool success = false;
11861 if (ConditionPassed(opcode)) {
11862 uint32_t regs;
11863 uint32_t alignment;
11864 uint32_t ebytes;
11865 uint32_t esize;
11866 uint32_t elements;
11867 uint32_t d;
11868 uint32_t n;
11869 uint32_t m;
11870 bool wback;
11871 bool register_index;
11873 switch (encoding) {
11874 case eEncodingT1:
11875 case eEncodingA1: {
11876 // case type of
11877 // when '0111'
11878 // regs = 1; if align<1> == '1' then UNDEFINED;
11879 // when '1010'
11880 // regs = 2; if align == '11' then UNDEFINED;
11881 // when '0110'
11882 // regs = 3; if align<1> == '1' then UNDEFINED;
11883 // when '0010'
11884 // regs = 4;
11885 // otherwise
11886 // SEE 'Related encodings';
11887 uint32_t type = Bits32(opcode, 11, 8);
11888 uint32_t align = Bits32(opcode, 5, 4);
11889 if (type == 7) // '0111'
11891 regs = 1;
11892 if (BitIsSet(align, 1))
11893 return false;
11894 } else if (type == 10) // '1010'
11896 regs = 2;
11897 if (align == 3)
11898 return false;
11900 } else if (type == 6) // '0110'
11902 regs = 3;
11903 if (BitIsSet(align, 1))
11904 return false;
11905 } else if (type == 2) // '0010'
11907 regs = 4;
11908 } else
11909 return false;
11911 // alignment = if align == '00' then 1 else 4 << UInt(align);
11912 if (align == 0)
11913 alignment = 1;
11914 else
11915 alignment = 4 << align;
11917 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11918 ebytes = 1 << Bits32(opcode, 7, 6);
11919 esize = 8 * ebytes;
11920 elements = 8 / ebytes;
11922 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11923 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11924 n = Bits32(opcode, 19, 15);
11925 m = Bits32(opcode, 3, 0);
11927 // wback = (m != 15); register_index = (m != 15 && m != 13);
11928 wback = (m != 15);
11929 register_index = ((m != 15) && (m != 13));
11931 // if d+regs > 32 then UNPREDICTABLE;
11932 if ((d + regs) > 32)
11933 return false;
11934 } break;
11936 default:
11937 return false;
11940 std::optional<RegisterInfo> base_reg =
11941 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
11943 uint32_t Rn = ReadCoreReg(n, &success);
11944 if (!success)
11945 return false;
11947 // address = R[n]; if (address MOD alignment) != 0 then
11948 // GenerateAlignmentException();
11949 addr_t address = Rn;
11950 if ((address % alignment) != 0)
11951 return false;
11953 EmulateInstruction::Context context;
11954 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11955 if (wback) {
11956 uint32_t Rm = ReadCoreReg(m, &success);
11957 if (!success)
11958 return false;
11960 uint32_t offset;
11961 if (register_index)
11962 offset = Rm;
11963 else
11964 offset = 8 * regs;
11966 uint32_t value = Rn + offset;
11967 context.type = eContextAdjustBaseRegister;
11968 context.SetRegisterPlusOffset(*base_reg, offset);
11970 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11971 value))
11972 return false;
11975 // for r = 0 to regs-1
11976 for (uint32_t r = 0; r < regs; ++r) {
11977 // for e = 0 to elements-1
11978 uint64_t assembled_data = 0;
11979 for (uint32_t e = 0; e < elements; ++e) {
11980 // Elem[D[d+r],e,esize] = MemU[address,ebytes];
11981 context.type = eContextRegisterLoad;
11982 context.SetRegisterPlusOffset(*base_reg, address - Rn);
11983 uint64_t data = MemURead(context, address, ebytes, 0, &success);
11984 if (!success)
11985 return false;
11987 assembled_data =
11988 (data << (e * esize)) |
11989 assembled_data; // New data goes to the left of existing data
11991 // address = address + ebytes;
11992 address = address + ebytes;
11994 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_d0 + d + r,
11995 assembled_data))
11996 return false;
11999 return true;
12002 // A8.6.308 VLD1 (single element to one lane)
12004 bool EmulateInstructionARM::EmulateVLD1Single(const uint32_t opcode,
12005 const ARMEncoding encoding) {
12006 #if 0
12007 if ConditionPassed() then
12008 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12009 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12010 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12011 Elem[D[d],index,esize] = MemU[address,ebytes];
12012 #endif
12014 bool success = false;
12016 if (ConditionPassed(opcode)) {
12017 uint32_t ebytes;
12018 uint32_t esize;
12019 uint32_t index;
12020 uint32_t alignment;
12021 uint32_t d;
12022 uint32_t n;
12023 uint32_t m;
12024 bool wback;
12025 bool register_index;
12027 switch (encoding) {
12028 case eEncodingT1:
12029 case eEncodingA1: {
12030 uint32_t size = Bits32(opcode, 11, 10);
12031 uint32_t index_align = Bits32(opcode, 7, 4);
12032 // if size == '11' then SEE VLD1 (single element to all lanes);
12033 if (size == 3)
12034 return EmulateVLD1SingleAll(opcode, encoding);
12035 // case size of
12036 if (size == 0) // when '00'
12038 // if index_align<0> != '0' then UNDEFINED;
12039 if (BitIsClear(index_align, 0))
12040 return false;
12042 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
12043 ebytes = 1;
12044 esize = 8;
12045 index = Bits32(index_align, 3, 1);
12046 alignment = 1;
12047 } else if (size == 1) // when '01'
12049 // if index_align<1> != '0' then UNDEFINED;
12050 if (BitIsClear(index_align, 1))
12051 return false;
12053 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
12054 ebytes = 2;
12055 esize = 16;
12056 index = Bits32(index_align, 3, 2);
12058 // alignment = if index_align<0> == '0' then 1 else 2;
12059 if (BitIsClear(index_align, 0))
12060 alignment = 1;
12061 else
12062 alignment = 2;
12063 } else if (size == 2) // when '10'
12065 // if index_align<2> != '0' then UNDEFINED;
12066 if (BitIsClear(index_align, 2))
12067 return false;
12069 // if index_align<1:0> != '00' && index_align<1:0> != '11' then
12070 // UNDEFINED;
12071 if ((Bits32(index_align, 1, 0) != 0) &&
12072 (Bits32(index_align, 1, 0) != 3))
12073 return false;
12075 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
12076 ebytes = 4;
12077 esize = 32;
12078 index = Bit32(index_align, 3);
12080 // alignment = if index_align<1:0> == '00' then 1 else 4;
12081 if (Bits32(index_align, 1, 0) == 0)
12082 alignment = 1;
12083 else
12084 alignment = 4;
12085 } else {
12086 return false;
12088 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12089 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12090 n = Bits32(opcode, 19, 16);
12091 m = Bits32(opcode, 3, 0);
12093 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15
12094 // then UNPREDICTABLE;
12095 wback = (m != 15);
12096 register_index = ((m != 15) && (m != 13));
12098 if (n == 15)
12099 return false;
12101 } break;
12103 default:
12104 return false;
12107 uint32_t Rn = ReadCoreReg(n, &success);
12108 if (!success)
12109 return false;
12111 // address = R[n]; if (address MOD alignment) != 0 then
12112 // GenerateAlignmentException();
12113 addr_t address = Rn;
12114 if ((address % alignment) != 0)
12115 return false;
12117 EmulateInstruction::Context context;
12118 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12119 if (wback) {
12120 uint32_t Rm = ReadCoreReg(m, &success);
12121 if (!success)
12122 return false;
12124 uint32_t offset;
12125 if (register_index)
12126 offset = Rm;
12127 else
12128 offset = ebytes;
12130 uint32_t value = Rn + offset;
12132 context.type = eContextAdjustBaseRegister;
12133 std::optional<RegisterInfo> base_reg =
12134 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
12135 context.SetRegisterPlusOffset(*base_reg, offset);
12137 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12138 value))
12139 return false;
12142 // Elem[D[d],index,esize] = MemU[address,ebytes];
12143 uint32_t element = MemURead(context, address, esize, 0, &success);
12144 if (!success)
12145 return false;
12147 element = element << (index * esize);
12149 uint64_t reg_data =
12150 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
12151 if (!success)
12152 return false;
12154 uint64_t all_ones = -1;
12155 uint64_t mask = all_ones
12156 << ((index + 1) * esize); // mask is all 1's to left of
12157 // where 'element' goes, & all 0's
12158 // at element & to the right of element.
12159 if (index > 0)
12160 mask = mask | Bits64(all_ones, (index * esize) - 1,
12161 0); // add 1's to the right of where 'element' goes.
12162 // now mask should be 0's where element goes & 1's everywhere else.
12164 uint64_t masked_reg =
12165 reg_data & mask; // Take original reg value & zero out 'element' bits
12166 reg_data =
12167 masked_reg & element; // Put 'element' into those bits in reg_data.
12169 context.type = eContextRegisterLoad;
12170 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
12171 reg_data))
12172 return false;
12174 return true;
12177 // A8.6.391 VST1 (multiple single elements) Vector Store (multiple single
12178 // elements) stores elements to memory from one, two, three, or four registers,
12179 // without interleaving. Every element of each register is stored.
12180 bool EmulateInstructionARM::EmulateVST1Multiple(const uint32_t opcode,
12181 ARMEncoding encoding) {
12182 #if 0
12183 if ConditionPassed() then
12184 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12185 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12186 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
12187 for r = 0 to regs-1
12188 for e = 0 to elements-1
12189 MemU[address,ebytes] = Elem[D[d+r],e,esize];
12190 address = address + ebytes;
12191 #endif
12193 bool success = false;
12195 if (ConditionPassed(opcode)) {
12196 uint32_t regs;
12197 uint32_t alignment;
12198 uint32_t ebytes;
12199 uint32_t esize;
12200 uint32_t elements;
12201 uint32_t d;
12202 uint32_t n;
12203 uint32_t m;
12204 bool wback;
12205 bool register_index;
12207 switch (encoding) {
12208 case eEncodingT1:
12209 case eEncodingA1: {
12210 uint32_t type = Bits32(opcode, 11, 8);
12211 uint32_t align = Bits32(opcode, 5, 4);
12213 // case type of
12214 if (type == 7) // when '0111'
12216 // regs = 1; if align<1> == '1' then UNDEFINED;
12217 regs = 1;
12218 if (BitIsSet(align, 1))
12219 return false;
12220 } else if (type == 10) // when '1010'
12222 // regs = 2; if align == '11' then UNDEFINED;
12223 regs = 2;
12224 if (align == 3)
12225 return false;
12226 } else if (type == 6) // when '0110'
12228 // regs = 3; if align<1> == '1' then UNDEFINED;
12229 regs = 3;
12230 if (BitIsSet(align, 1))
12231 return false;
12232 } else if (type == 2) // when '0010'
12233 // regs = 4;
12234 regs = 4;
12235 else // otherwise
12236 // SEE 'Related encodings';
12237 return false;
12239 // alignment = if align == '00' then 1 else 4 << UInt(align);
12240 if (align == 0)
12241 alignment = 1;
12242 else
12243 alignment = 4 << align;
12245 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
12246 ebytes = 1 << Bits32(opcode, 7, 6);
12247 esize = 8 * ebytes;
12248 elements = 8 / ebytes;
12250 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12251 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12252 n = Bits32(opcode, 19, 16);
12253 m = Bits32(opcode, 3, 0);
12255 // wback = (m != 15); register_index = (m != 15 && m != 13);
12256 wback = (m != 15);
12257 register_index = ((m != 15) && (m != 13));
12259 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
12260 if ((d + regs) > 32)
12261 return false;
12263 if (n == 15)
12264 return false;
12266 } break;
12268 default:
12269 return false;
12272 std::optional<RegisterInfo> base_reg =
12273 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
12275 uint32_t Rn = ReadCoreReg(n, &success);
12276 if (!success)
12277 return false;
12279 // address = R[n]; if (address MOD alignment) != 0 then
12280 // GenerateAlignmentException();
12281 addr_t address = Rn;
12282 if ((address % alignment) != 0)
12283 return false;
12285 EmulateInstruction::Context context;
12286 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
12287 if (wback) {
12288 uint32_t Rm = ReadCoreReg(m, &success);
12289 if (!success)
12290 return false;
12292 uint32_t offset;
12293 if (register_index)
12294 offset = Rm;
12295 else
12296 offset = 8 * regs;
12298 context.type = eContextAdjustBaseRegister;
12299 context.SetRegisterPlusOffset(*base_reg, offset);
12301 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12302 Rn + offset))
12303 return false;
12306 context.type = eContextRegisterStore;
12307 // for r = 0 to regs-1
12308 for (uint32_t r = 0; r < regs; ++r) {
12309 std::optional<RegisterInfo> data_reg =
12310 GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d + r);
12311 uint64_t register_data = ReadRegisterUnsigned(
12312 eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);
12313 if (!success)
12314 return false;
12316 // for e = 0 to elements-1
12317 for (uint32_t e = 0; e < elements; ++e) {
12318 // MemU[address,ebytes] = Elem[D[d+r],e,esize];
12319 uint64_t word = Bits64(register_data, ((e + 1) * esize) - 1, e * esize);
12321 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
12322 address - Rn);
12323 if (!MemUWrite(context, address, word, ebytes))
12324 return false;
12326 // address = address + ebytes;
12327 address = address + ebytes;
12331 return true;
12334 // A8.6.392 VST1 (single element from one lane) This instruction stores one
12335 // element to memory from one element of a register.
12336 bool EmulateInstructionARM::EmulateVST1Single(const uint32_t opcode,
12337 ARMEncoding encoding) {
12338 #if 0
12339 if ConditionPassed() then
12340 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12341 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12342 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12343 MemU[address,ebytes] = Elem[D[d],index,esize];
12344 #endif
12346 bool success = false;
12348 if (ConditionPassed(opcode)) {
12349 uint32_t ebytes;
12350 uint32_t esize;
12351 uint32_t index;
12352 uint32_t alignment;
12353 uint32_t d;
12354 uint32_t n;
12355 uint32_t m;
12356 bool wback;
12357 bool register_index;
12359 switch (encoding) {
12360 case eEncodingT1:
12361 case eEncodingA1: {
12362 uint32_t size = Bits32(opcode, 11, 10);
12363 uint32_t index_align = Bits32(opcode, 7, 4);
12365 // if size == '11' then UNDEFINED;
12366 if (size == 3)
12367 return false;
12369 // case size of
12370 if (size == 0) // when '00'
12372 // if index_align<0> != '0' then UNDEFINED;
12373 if (BitIsClear(index_align, 0))
12374 return false;
12375 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
12376 ebytes = 1;
12377 esize = 8;
12378 index = Bits32(index_align, 3, 1);
12379 alignment = 1;
12380 } else if (size == 1) // when '01'
12382 // if index_align<1> != '0' then UNDEFINED;
12383 if (BitIsClear(index_align, 1))
12384 return false;
12386 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
12387 ebytes = 2;
12388 esize = 16;
12389 index = Bits32(index_align, 3, 2);
12391 // alignment = if index_align<0> == '0' then 1 else 2;
12392 if (BitIsClear(index_align, 0))
12393 alignment = 1;
12394 else
12395 alignment = 2;
12396 } else if (size == 2) // when '10'
12398 // if index_align<2> != '0' then UNDEFINED;
12399 if (BitIsClear(index_align, 2))
12400 return false;
12402 // if index_align<1:0> != '00' && index_align<1:0> != '11' then
12403 // UNDEFINED;
12404 if ((Bits32(index_align, 1, 0) != 0) &&
12405 (Bits32(index_align, 1, 0) != 3))
12406 return false;
12408 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
12409 ebytes = 4;
12410 esize = 32;
12411 index = Bit32(index_align, 3);
12413 // alignment = if index_align<1:0> == '00' then 1 else 4;
12414 if (Bits32(index_align, 1, 0) == 0)
12415 alignment = 1;
12416 else
12417 alignment = 4;
12418 } else {
12419 return false;
12421 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12422 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12423 n = Bits32(opcode, 19, 16);
12424 m = Bits32(opcode, 3, 0);
12426 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15
12427 // then UNPREDICTABLE;
12428 wback = (m != 15);
12429 register_index = ((m != 15) && (m != 13));
12431 if (n == 15)
12432 return false;
12433 } break;
12435 default:
12436 return false;
12439 std::optional<RegisterInfo> base_reg =
12440 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
12442 uint32_t Rn = ReadCoreReg(n, &success);
12443 if (!success)
12444 return false;
12446 // address = R[n]; if (address MOD alignment) != 0 then
12447 // GenerateAlignmentException();
12448 addr_t address = Rn;
12449 if ((address % alignment) != 0)
12450 return false;
12452 EmulateInstruction::Context context;
12453 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12454 if (wback) {
12455 uint32_t Rm = ReadCoreReg(m, &success);
12456 if (!success)
12457 return false;
12459 uint32_t offset;
12460 if (register_index)
12461 offset = Rm;
12462 else
12463 offset = ebytes;
12465 context.type = eContextAdjustBaseRegister;
12466 context.SetRegisterPlusOffset(*base_reg, offset);
12468 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12469 Rn + offset))
12470 return false;
12473 // MemU[address,ebytes] = Elem[D[d],index,esize];
12474 uint64_t register_data =
12475 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
12476 if (!success)
12477 return false;
12479 uint64_t word =
12480 Bits64(register_data, ((index + 1) * esize) - 1, index * esize);
12482 std::optional<RegisterInfo> data_reg =
12483 GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d);
12484 context.type = eContextRegisterStore;
12485 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);
12487 if (!MemUWrite(context, address, word, ebytes))
12488 return false;
12490 return true;
12493 // A8.6.309 VLD1 (single element to all lanes) This instruction loads one
12494 // element from memory into every element of one or two vectors.
12495 bool EmulateInstructionARM::EmulateVLD1SingleAll(const uint32_t opcode,
12496 const ARMEncoding encoding) {
12497 #if 0
12498 if ConditionPassed() then
12499 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12500 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12501 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12502 replicated_element = Replicate(MemU[address,ebytes], elements);
12503 for r = 0 to regs-1
12504 D[d+r] = replicated_element;
12505 #endif
12507 bool success = false;
12509 if (ConditionPassed(opcode)) {
12510 uint32_t ebytes;
12511 uint32_t elements;
12512 uint32_t regs;
12513 uint32_t alignment;
12514 uint32_t d;
12515 uint32_t n;
12516 uint32_t m;
12517 bool wback;
12518 bool register_index;
12520 switch (encoding) {
12521 case eEncodingT1:
12522 case eEncodingA1: {
12523 // if size == '11' || (size == '00' && a == '1') then UNDEFINED;
12524 uint32_t size = Bits32(opcode, 7, 6);
12525 if ((size == 3) || ((size == 0) && BitIsSet(opcode, 4)))
12526 return false;
12528 // ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == '0'
12529 // then 1 else 2;
12530 ebytes = 1 << size;
12531 elements = 8 / ebytes;
12532 if (BitIsClear(opcode, 5))
12533 regs = 1;
12534 else
12535 regs = 2;
12537 // alignment = if a == '0' then 1 else ebytes;
12538 if (BitIsClear(opcode, 4))
12539 alignment = 1;
12540 else
12541 alignment = ebytes;
12543 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12544 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12545 n = Bits32(opcode, 19, 16);
12546 m = Bits32(opcode, 3, 0);
12548 // wback = (m != 15); register_index = (m != 15 && m != 13);
12549 wback = (m != 15);
12550 register_index = ((m != 15) && (m != 13));
12552 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
12553 if ((d + regs) > 32)
12554 return false;
12556 if (n == 15)
12557 return false;
12558 } break;
12560 default:
12561 return false;
12564 uint32_t Rn = ReadCoreReg(n, &success);
12565 if (!success)
12566 return false;
12568 // address = R[n]; if (address MOD alignment) != 0 then
12569 // GenerateAlignmentException();
12570 addr_t address = Rn;
12571 if ((address % alignment) != 0)
12572 return false;
12574 EmulateInstruction::Context context;
12575 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12576 if (wback) {
12577 uint32_t Rm = ReadCoreReg(m, &success);
12578 if (!success)
12579 return false;
12581 uint32_t offset;
12582 if (register_index)
12583 offset = Rm;
12584 else
12585 offset = ebytes;
12587 context.type = eContextAdjustBaseRegister;
12588 std::optional<RegisterInfo> base_reg =
12589 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
12590 context.SetRegisterPlusOffset(*base_reg, offset);
12592 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12593 Rn + offset))
12594 return false;
12597 // replicated_element = Replicate(MemU[address,ebytes], elements);
12599 context.type = eContextRegisterLoad;
12600 uint64_t word = MemURead(context, address, ebytes, 0, &success);
12601 if (!success)
12602 return false;
12604 uint64_t replicated_element = 0;
12605 uint32_t esize = ebytes * 8;
12606 for (uint32_t e = 0; e < elements; ++e)
12607 replicated_element =
12608 (replicated_element << esize) | Bits64(word, esize - 1, 0);
12610 // for r = 0 to regs-1
12611 for (uint32_t r = 0; r < regs; ++r) {
12612 // D[d+r] = replicated_element;
12613 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_d0 + d + r,
12614 replicated_element))
12615 return false;
12618 return true;
12621 // B6.2.13 SUBS PC, LR and related instructions The SUBS PC, LR, #<const?
12622 // instruction provides an exception return without the use of the stack. It
12623 // subtracts the immediate constant from the LR, branches to the resulting
12624 // address, and also copies the SPSR to the CPSR.
12625 bool EmulateInstructionARM::EmulateSUBSPcLrEtc(const uint32_t opcode,
12626 const ARMEncoding encoding) {
12627 #if 0
12628 if ConditionPassed() then
12629 EncodingSpecificOperations();
12630 if CurrentInstrSet() == InstrSet_ThumbEE then
12631 UNPREDICTABLE;
12632 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
12633 case opcode of
12634 when '0000' result = R[n] AND operand2; // AND
12635 when '0001' result = R[n] EOR operand2; // EOR
12636 when '0010' (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB
12637 when '0011' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB
12638 when '0100' (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD
12639 when '0101' (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12640 when '0110' (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12641 when '0111' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12642 when '1100' result = R[n] OR operand2; // ORR
12643 when '1101' result = operand2; // MOV
12644 when '1110' result = R[n] AND NOT(operand2); // BIC
12645 when '1111' result = NOT(operand2); // MVN
12646 CPSRWriteByInstr(SPSR[], '1111', TRUE);
12647 BranchWritePC(result);
12648 #endif
12650 bool success = false;
12652 if (ConditionPassed(opcode)) {
12653 uint32_t n;
12654 uint32_t m;
12655 uint32_t imm32;
12656 bool register_form;
12657 ARM_ShifterType shift_t;
12658 uint32_t shift_n;
12659 uint32_t code;
12661 switch (encoding) {
12662 case eEncodingT1:
12663 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE n = 14;
12664 // imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = '0010';
12665 // // = SUB
12666 n = 14;
12667 imm32 = Bits32(opcode, 7, 0);
12668 register_form = false;
12669 code = 2;
12671 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
12672 if (InITBlock() && !LastInITBlock())
12673 return false;
12675 break;
12677 case eEncodingA1:
12678 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
12679 n = Bits32(opcode, 19, 16);
12680 imm32 = ARMExpandImm(opcode);
12681 register_form = false;
12682 code = Bits32(opcode, 24, 21);
12684 break;
12686 case eEncodingA2:
12687 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
12688 n = Bits32(opcode, 19, 16);
12689 m = Bits32(opcode, 3, 0);
12690 register_form = true;
12692 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
12693 shift_n = DecodeImmShiftARM(opcode, shift_t);
12695 break;
12697 default:
12698 return false;
12701 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C)
12702 // else imm32;
12703 uint32_t operand2;
12704 if (register_form) {
12705 uint32_t Rm = ReadCoreReg(m, &success);
12706 if (!success)
12707 return false;
12709 operand2 = Shift(Rm, shift_t, shift_n, APSR_C, &success);
12710 if (!success)
12711 return false;
12712 } else {
12713 operand2 = imm32;
12716 uint32_t Rn = ReadCoreReg(n, &success);
12717 if (!success)
12718 return false;
12720 AddWithCarryResult result;
12722 // case opcode of
12723 switch (code) {
12724 case 0: // when '0000'
12725 // result = R[n] AND operand2; // AND
12726 result.result = Rn & operand2;
12727 break;
12729 case 1: // when '0001'
12730 // result = R[n] EOR operand2; // EOR
12731 result.result = Rn ^ operand2;
12732 break;
12734 case 2: // when '0010'
12735 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB
12736 result = AddWithCarry(Rn, ~(operand2), 1);
12737 break;
12739 case 3: // when '0011'
12740 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB
12741 result = AddWithCarry(~(Rn), operand2, 1);
12742 break;
12744 case 4: // when '0100'
12745 // (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD
12746 result = AddWithCarry(Rn, operand2, 0);
12747 break;
12749 case 5: // when '0101'
12750 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12751 result = AddWithCarry(Rn, operand2, APSR_C);
12752 break;
12754 case 6: // when '0110'
12755 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12756 result = AddWithCarry(Rn, ~(operand2), APSR_C);
12757 break;
12759 case 7: // when '0111'
12760 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12761 result = AddWithCarry(~(Rn), operand2, APSR_C);
12762 break;
12764 case 10: // when '1100'
12765 // result = R[n] OR operand2; // ORR
12766 result.result = Rn | operand2;
12767 break;
12769 case 11: // when '1101'
12770 // result = operand2; // MOV
12771 result.result = operand2;
12772 break;
12774 case 12: // when '1110'
12775 // result = R[n] AND NOT(operand2); // BIC
12776 result.result = Rn & ~(operand2);
12777 break;
12779 case 15: // when '1111'
12780 // result = NOT(operand2); // MVN
12781 result.result = ~(operand2);
12782 break;
12784 default:
12785 return false;
12787 // CPSRWriteByInstr(SPSR[], '1111', TRUE);
12789 // For now, in emulation mode, we don't have access to the SPSR, so we will
12790 // use the CPSR instead, and hope for the best.
12791 uint32_t spsr =
12792 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success);
12793 if (!success)
12794 return false;
12796 CPSRWriteByInstr(spsr, 15, true);
12798 // BranchWritePC(result);
12799 EmulateInstruction::Context context;
12800 context.type = eContextAdjustPC;
12801 context.SetImmediate(result.result);
12803 BranchWritePC(context, result.result);
12805 return true;
12808 EmulateInstructionARM::ARMOpcode *
12809 EmulateInstructionARM::GetARMOpcodeForInstruction(const uint32_t opcode,
12810 uint32_t arm_isa) {
12811 static ARMOpcode g_arm_opcodes[] = {
12812 // Prologue instructions
12814 // push register(s)
12815 {0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12816 &EmulateInstructionARM::EmulatePUSH, "push <registers>"},
12817 {0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32,
12818 &EmulateInstructionARM::EmulatePUSH, "push <register>"},
12820 // set r7 to point to a stack offset
12821 {0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12822 &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>"},
12823 {0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12824 &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
12825 // copy the stack pointer to ip
12826 {0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32,
12827 &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp"},
12828 {0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12829 &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>"},
12830 {0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12831 &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
12833 // adjust the stack pointer
12834 {0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12835 &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
12836 {0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12837 &EmulateInstructionARM::EmulateSUBSPReg,
12838 "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},
12840 // push one register
12841 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
12842 {0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12843 &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!"},
12845 // vector push consecutive extension register(s)
12846 {0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32,
12847 &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12848 {0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,
12849 &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
12851 // Epilogue instructions
12853 {0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12854 &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12855 {0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32,
12856 &EmulateInstructionARM::EmulatePOP, "pop <register>"},
12857 {0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32,
12858 &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12859 {0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,
12860 &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
12862 // Supervisor Call (previously Software Interrupt)
12863 {0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12864 &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
12866 // Branch instructions
12867 // To resolve ambiguity, "blx <label>" should come before "b #imm24" and
12868 // "bl <label>".
12869 {0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32,
12870 &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12871 {0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12872 &EmulateInstructionARM::EmulateB, "b #imm24"},
12873 {0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12874 &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
12875 {0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32,
12876 &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
12877 // for example, "bx lr"
12878 {0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32,
12879 &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
12880 // bxj
12881 {0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32,
12882 &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
12884 // Data-processing instructions
12885 // adc (immediate)
12886 {0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12887 &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
12888 // adc (register)
12889 {0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12890 &EmulateInstructionARM::EmulateADCReg,
12891 "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12892 // add (immediate)
12893 {0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12894 &EmulateInstructionARM::EmulateADDImmARM,
12895 "add{s}<c> <Rd>, <Rn>, #const"},
12896 // add (register)
12897 {0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12898 &EmulateInstructionARM::EmulateADDReg,
12899 "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12900 // add (register-shifted register)
12901 {0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32,
12902 &EmulateInstructionARM::EmulateADDRegShift,
12903 "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
12904 // adr
12905 {0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12906 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12907 {0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32,
12908 &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
12909 // and (immediate)
12910 {0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12911 &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
12912 // and (register)
12913 {0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12914 &EmulateInstructionARM::EmulateANDReg,
12915 "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12916 // bic (immediate)
12917 {0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12918 &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
12919 // bic (register)
12920 {0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12921 &EmulateInstructionARM::EmulateBICReg,
12922 "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12923 // eor (immediate)
12924 {0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12925 &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
12926 // eor (register)
12927 {0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12928 &EmulateInstructionARM::EmulateEORReg,
12929 "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12930 // orr (immediate)
12931 {0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12932 &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
12933 // orr (register)
12934 {0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12935 &EmulateInstructionARM::EmulateORRReg,
12936 "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12937 // rsb (immediate)
12938 {0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12939 &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
12940 // rsb (register)
12941 {0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12942 &EmulateInstructionARM::EmulateRSBReg,
12943 "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12944 // rsc (immediate)
12945 {0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12946 &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
12947 // rsc (register)
12948 {0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12949 &EmulateInstructionARM::EmulateRSCReg,
12950 "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12951 // sbc (immediate)
12952 {0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12953 &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
12954 // sbc (register)
12955 {0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12956 &EmulateInstructionARM::EmulateSBCReg,
12957 "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12958 // sub (immediate, ARM)
12959 {0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12960 &EmulateInstructionARM::EmulateSUBImmARM,
12961 "sub{s}<c> <Rd>, <Rn>, #<const>"},
12962 // sub (sp minus immediate)
12963 {0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12964 &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
12965 // sub (register)
12966 {0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12967 &EmulateInstructionARM::EmulateSUBReg,
12968 "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
12969 // teq (immediate)
12970 {0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12971 &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
12972 // teq (register)
12973 {0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12974 &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
12975 // tst (immediate)
12976 {0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12977 &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
12978 // tst (register)
12979 {0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12980 &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
12982 // mov (immediate)
12983 {0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12984 &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
12985 {0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,
12986 &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>"},
12987 // mov (register)
12988 {0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12989 &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
12990 // mvn (immediate)
12991 {0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12992 &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
12993 // mvn (register)
12994 {0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12995 &EmulateInstructionARM::EmulateMVNReg,
12996 "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
12997 // cmn (immediate)
12998 {0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12999 &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
13000 // cmn (register)
13001 {0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13002 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
13003 // cmp (immediate)
13004 {0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13005 &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
13006 // cmp (register)
13007 {0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13008 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
13009 // asr (immediate)
13010 {0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32,
13011 &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
13012 // asr (register)
13013 {0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32,
13014 &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
13015 // lsl (immediate)
13016 {0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13017 &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
13018 // lsl (register)
13019 {0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32,
13020 &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
13021 // lsr (immediate)
13022 {0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32,
13023 &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
13024 // lsr (register)
13025 {0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32,
13026 &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
13027 // rrx is a special case encoding of ror (immediate)
13028 {0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32,
13029 &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
13030 // ror (immediate)
13031 {0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32,
13032 &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
13033 // ror (register)
13034 {0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32,
13035 &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
13036 // mul
13037 {0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32,
13038 &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>"},
13040 // subs pc, lr and related instructions
13041 {0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13042 &EmulateInstructionARM::EmulateSUBSPcLrEtc,
13043 "<opc>S<c> PC,#<const> | <Rn>,#<const>"},
13044 {0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32,
13045 &EmulateInstructionARM::EmulateSUBSPcLrEtc,
13046 "<opc>S<c> PC,<Rn>,<Rm{,<shift>}"},
13048 // Load instructions
13049 {0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13050 &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"},
13051 {0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13052 &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>"},
13053 {0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13054 &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"},
13055 {0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13056 &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>"},
13057 {0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13058 &EmulateInstructionARM::EmulateLDRImmediateARM,
13059 "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]"},
13060 {0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13061 &EmulateInstructionARM::EmulateLDRRegister,
13062 "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}"},
13063 {0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13064 &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
13065 {0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13066 &EmulateInstructionARM::EmulateLDRBRegister,
13067 "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}"},
13068 {0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13069 &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"},
13070 {0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13071 &EmulateInstructionARM::EmulateLDRHRegister,
13072 "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13073 {0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13074 &EmulateInstructionARM::EmulateLDRSBImmediate,
13075 "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]"},
13076 {0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13077 &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>"},
13078 {0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13079 &EmulateInstructionARM::EmulateLDRSBRegister,
13080 "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13081 {0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13082 &EmulateInstructionARM::EmulateLDRSHImmediate,
13083 "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
13084 {0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13085 &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"},
13086 {0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13087 &EmulateInstructionARM::EmulateLDRSHRegister,
13088 "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13089 {0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13090 &EmulateInstructionARM::EmulateLDRDImmediate,
13091 "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
13092 {0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13093 &EmulateInstructionARM::EmulateLDRDRegister,
13094 "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
13095 {0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13096 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13097 {0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13098 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13099 {0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13100 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13101 {0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13102 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
13103 {0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13104 &EmulateInstructionARM::EmulateVLD1Multiple,
13105 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13106 {0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13107 &EmulateInstructionARM::EmulateVLD1Single,
13108 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13109 {0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13110 &EmulateInstructionARM::EmulateVLD1SingleAll,
13111 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13113 // Store instructions
13114 {0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13115 &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"},
13116 {0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13117 &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>"},
13118 {0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13119 &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"},
13120 {0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13121 &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>"},
13122 {0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13123 &EmulateInstructionARM::EmulateSTRRegister,
13124 "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}"},
13125 {0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13126 &EmulateInstructionARM::EmulateSTRHRegister,
13127 "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}"},
13128 {0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13129 &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
13130 {0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13131 &EmulateInstructionARM::EmulateSTRBImmARM,
13132 "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
13133 {0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13134 &EmulateInstructionARM::EmulateSTRImmARM,
13135 "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
13136 {0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13137 &EmulateInstructionARM::EmulateSTRDImm,
13138 "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
13139 {0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13140 &EmulateInstructionARM::EmulateSTRDReg,
13141 "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
13142 {0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13143 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
13144 {0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13145 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
13146 {0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13147 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
13148 {0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13149 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
13150 {0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13151 &EmulateInstructionARM::EmulateVST1Multiple,
13152 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13153 {0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13154 &EmulateInstructionARM::EmulateVST1Single,
13155 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13157 // Other instructions
13158 {0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13159 &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}"},
13160 {0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13161 &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}"},
13162 {0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13163 &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}"},
13164 {0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13165 &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}"},
13166 {0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13167 &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}"}
13170 static const size_t k_num_arm_opcodes = std::size(g_arm_opcodes);
13172 for (size_t i = 0; i < k_num_arm_opcodes; ++i) {
13173 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value &&
13174 (g_arm_opcodes[i].variants & arm_isa) != 0)
13175 return &g_arm_opcodes[i];
13177 return nullptr;
13180 EmulateInstructionARM::ARMOpcode *
13181 EmulateInstructionARM::GetThumbOpcodeForInstruction(const uint32_t opcode,
13182 uint32_t arm_isa) {
13184 static ARMOpcode g_thumb_opcodes[] = {
13185 // Prologue instructions
13187 // push register(s)
13188 {0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16,
13189 &EmulateInstructionARM::EmulatePUSH, "push <registers>"},
13190 {0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13191 &EmulateInstructionARM::EmulatePUSH, "push.w <registers>"},
13192 {0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13193 &EmulateInstructionARM::EmulatePUSH, "push.w <register>"},
13195 // set r7 to point to a stack offset
13196 {0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13197 &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm"},
13198 // copy the stack pointer to r7
13199 {0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16,
13200 &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp"},
13201 // move from high register to low register (comes after "mov r7, sp" to
13202 // resolve ambiguity)
13203 {0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16,
13204 &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15"},
13206 // PC-relative load into register (see also EmulateADDSPRm)
13207 {0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13208 &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
13210 // adjust the stack pointer
13211 {0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16,
13212 &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
13213 {0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16,
13214 &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
13215 {0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13216 &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
13217 {0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13218 &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
13219 {0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13220 &EmulateInstructionARM::EmulateSUBSPReg,
13221 "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},
13223 // vector push consecutive extension register(s)
13224 {0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13225 &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
13226 {0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13227 &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
13229 // Epilogue instructions
13231 {0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13232 &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
13233 {0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16,
13234 &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
13235 {0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13236 &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
13237 {0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13238 &EmulateInstructionARM::EmulatePOP, "pop.w <registers>"},
13239 {0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13240 &EmulateInstructionARM::EmulatePOP, "pop.w <register>"},
13241 {0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13242 &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
13243 {0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13244 &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
13246 // Supervisor Call (previously Software Interrupt)
13247 {0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13248 &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
13250 // If Then makes up to four following instructions conditional.
13251 // The next 5 opcode _must_ come before the if then instruction
13252 {0xffffffff, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13253 &EmulateInstructionARM::EmulateNop, "nop"},
13254 {0xffffffff, 0x0000bf10, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13255 &EmulateInstructionARM::EmulateNop, "nop YIELD (yield hint)"},
13256 {0xffffffff, 0x0000bf20, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13257 &EmulateInstructionARM::EmulateNop, "nop WFE (wait for event hint)"},
13258 {0xffffffff, 0x0000bf30, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13259 &EmulateInstructionARM::EmulateNop, "nop WFI (wait for interrupt hint)"},
13260 {0xffffffff, 0x0000bf40, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13261 &EmulateInstructionARM::EmulateNop, "nop SEV (send event hint)"},
13262 {0xffffff00, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13263 &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
13265 // Branch instructions
13266 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
13267 {0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13268 &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
13269 {0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16,
13270 &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
13271 {0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13272 &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
13273 {0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13274 &EmulateInstructionARM::EmulateB,
13275 "b<c>.w #imm8 (outside or last in IT)"},
13276 // J1 == J2 == 1
13277 {0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32,
13278 &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
13279 // J1 == J2 == 1
13280 {0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32,
13281 &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
13282 {0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16,
13283 &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
13284 // for example, "bx lr"
13285 {0xffffff87, 0x00004700, ARMvAll, eEncodingT1, No_VFP, eSize32,
13286 &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
13287 // bxj
13288 {0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32,
13289 &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
13290 // compare and branch
13291 {0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13292 &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
13293 // table branch byte
13294 {0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13295 &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
13296 // table branch halfword
13297 {0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13298 &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
13300 // Data-processing instructions
13301 // adc (immediate)
13302 {0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13303 &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
13304 // adc (register)
13305 {0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16,
13306 &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
13307 {0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13308 &EmulateInstructionARM::EmulateADCReg,
13309 "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13310 // add (register)
13311 {0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13312 &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
13313 // Make sure "add sp, <Rm>" comes before this instruction, so there's no
13314 // ambiguity decoding the two.
13315 {0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16,
13316 &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
13317 // adr
13318 {0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13319 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
13320 {0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13321 &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
13322 {0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13323 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
13324 // and (immediate)
13325 {0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13326 &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
13327 // and (register)
13328 {0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13329 &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
13330 {0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13331 &EmulateInstructionARM::EmulateANDReg,
13332 "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13333 // bic (immediate)
13334 {0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13335 &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
13336 // bic (register)
13337 {0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16,
13338 &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
13339 {0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13340 &EmulateInstructionARM::EmulateBICReg,
13341 "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13342 // eor (immediate)
13343 {0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13344 &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
13345 // eor (register)
13346 {0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16,
13347 &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
13348 {0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13349 &EmulateInstructionARM::EmulateEORReg,
13350 "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13351 // orr (immediate)
13352 {0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13353 &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
13354 // orr (register)
13355 {0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16,
13356 &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
13357 {0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13358 &EmulateInstructionARM::EmulateORRReg,
13359 "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13360 // rsb (immediate)
13361 {0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16,
13362 &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
13363 {0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13364 &EmulateInstructionARM::EmulateRSBImm,
13365 "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
13366 // rsb (register)
13367 {0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13368 &EmulateInstructionARM::EmulateRSBReg,
13369 "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13370 // sbc (immediate)
13371 {0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13372 &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
13373 // sbc (register)
13374 {0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16,
13375 &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
13376 {0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13377 &EmulateInstructionARM::EmulateSBCReg,
13378 "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13379 // add (immediate, Thumb)
13380 {0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13381 &EmulateInstructionARM::EmulateADDImmThumb,
13382 "adds|add<c> <Rd>,<Rn>,#<imm3>"},
13383 {0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,
13384 &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>"},
13385 {0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13386 &EmulateInstructionARM::EmulateADDImmThumb,
13387 "add{s}<c>.w <Rd>,<Rn>,#<const>"},
13388 {0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13389 &EmulateInstructionARM::EmulateADDImmThumb,
13390 "addw<c> <Rd>,<Rn>,#<imm12>"},
13391 // sub (immediate, Thumb)
13392 {0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13393 &EmulateInstructionARM::EmulateSUBImmThumb,
13394 "subs|sub<c> <Rd>, <Rn> #imm3"},
13395 {0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16,
13396 &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
13397 {0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13398 &EmulateInstructionARM::EmulateSUBImmThumb,
13399 "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
13400 {0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13401 &EmulateInstructionARM::EmulateSUBImmThumb,
13402 "subw<c> <Rd>, <Rn>, #imm12"},
13403 // sub (sp minus immediate)
13404 {0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13405 &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
13406 {0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13407 &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
13408 // sub (register)
13409 {0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13410 &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
13411 {0xffe08000, 0xeba00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13412 &EmulateInstructionARM::EmulateSUBReg,
13413 "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"},
13414 // teq (immediate)
13415 {0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13416 &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
13417 // teq (register)
13418 {0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13419 &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
13420 // tst (immediate)
13421 {0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13422 &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
13423 // tst (register)
13424 {0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16,
13425 &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
13426 {0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13427 &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
13429 // move from high register to high register
13430 {0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16,
13431 &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
13432 // move from low register to low register
13433 {0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16,
13434 &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
13435 // mov{s}<c>.w <Rd>, <Rm>
13436 {0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13437 &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
13438 // move immediate
13439 {0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13440 &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
13441 {0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13442 &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
13443 {0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13444 &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
13445 // mvn (immediate)
13446 {0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13447 &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
13448 // mvn (register)
13449 {0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13450 &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
13451 {0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13452 &EmulateInstructionARM::EmulateMVNReg,
13453 "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
13454 // cmn (immediate)
13455 {0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13456 &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
13457 // cmn (register)
13458 {0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13459 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
13460 {0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13461 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
13462 // cmp (immediate)
13463 {0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13464 &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
13465 {0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13466 &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
13467 // cmp (register) (Rn and Rm both from r0-r7)
13468 {0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16,
13469 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
13470 // cmp (register) (Rn and Rm not both from r0-r7)
13471 {0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16,
13472 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
13473 {0xfff08f00, 0xebb00f00, ARMvAll, eEncodingT3, No_VFP, eSize16,
13474 &EmulateInstructionARM::EmulateCMPReg,
13475 "cmp<c>.w <Rn>, <Rm> {, <shift>}"},
13476 // asr (immediate)
13477 {0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13478 &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
13479 {0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13480 &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
13481 // asr (register)
13482 {0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16,
13483 &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
13484 {0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13485 &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
13486 // lsl (immediate)
13487 {0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13488 &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
13489 {0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13490 &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
13491 // lsl (register)
13492 {0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16,
13493 &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
13494 {0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13495 &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
13496 // lsr (immediate)
13497 {0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13498 &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
13499 {0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13500 &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
13501 // lsr (register)
13502 {0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13503 &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
13504 {0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13505 &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
13506 // rrx is a special case encoding of ror (immediate)
13507 {0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13508 &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
13509 // ror (immediate)
13510 {0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13511 &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
13512 // ror (register)
13513 {0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13514 &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
13515 {0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13516 &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
13517 // mul
13518 {0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13519 &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>"},
13520 // mul
13521 {0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13522 &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>"},
13524 // subs pc, lr and related instructions
13525 {0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13526 &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>"},
13528 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE
13529 // LDM.. Instructions in this table;
13530 // otherwise the wrong instructions will be selected.
13532 {0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13533 &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}"},
13534 {0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13535 &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}"},
13537 // Load instructions
13538 {0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13539 &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"},
13540 {0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13541 &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>"},
13542 {0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13543 &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"},
13544 {0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13545 &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
13546 {0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,
13547 &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
13548 {0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13549 &EmulateInstructionARM::EmulateLDRRtRnImm,
13550 "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
13551 {0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13552 &EmulateInstructionARM::EmulateLDRRtRnImm,
13553 "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
13554 // Thumb2 PC-relative load into register
13555 {0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13556 &EmulateInstructionARM::EmulateLDRRtPCRelative,
13557 "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
13558 {0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13559 &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]"},
13560 {0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13561 &EmulateInstructionARM::EmulateLDRRegister,
13562 "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]"},
13563 {0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13564 &EmulateInstructionARM::EmulateLDRBImmediate,
13565 "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]"},
13566 {0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13567 &EmulateInstructionARM::EmulateLDRBImmediate,
13568 "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]"},
13569 {0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13570 &EmulateInstructionARM::EmulateLDRBImmediate,
13571 "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}"},
13572 {0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13573 &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]"},
13574 {0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13575 &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]"},
13576 {0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13577 &EmulateInstructionARM::EmulateLDRBRegister,
13578 "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},
13579 {0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13580 &EmulateInstructionARM::EmulateLDRHImmediate,
13581 "ldrh<c> <Rt>, [<Rn>{,#<imm>}]"},
13582 {0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13583 &EmulateInstructionARM::EmulateLDRHImmediate,
13584 "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]"},
13585 {0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13586 &EmulateInstructionARM::EmulateLDRHImmediate,
13587 "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}"},
13588 {0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13589 &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"},
13590 {0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13591 &EmulateInstructionARM::EmulateLDRHRegister,
13592 "ldrh<c> <Rt>, [<Rn>,<Rm>]"},
13593 {0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13594 &EmulateInstructionARM::EmulateLDRHRegister,
13595 "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13596 {0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13597 &EmulateInstructionARM::EmulateLDRSBImmediate,
13598 "ldrsb<c> <Rt>,[<Rn>,#<imm12>]"},
13599 {0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13600 &EmulateInstructionARM::EmulateLDRSBImmediate,
13601 "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]"},
13602 {0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13603 &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>"},
13604 {0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13605 &EmulateInstructionARM::EmulateLDRSBRegister,
13606 "ldrsb<c> <Rt>,[<Rn>,<Rm>]"},
13607 {0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13608 &EmulateInstructionARM::EmulateLDRSBRegister,
13609 "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},
13610 {0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13611 &EmulateInstructionARM::EmulateLDRSHImmediate,
13612 "ldrsh<c> <Rt>,[<Rn>,#<imm12>]"},
13613 {0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13614 &EmulateInstructionARM::EmulateLDRSHImmediate,
13615 "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]"},
13616 {0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13617 &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"},
13618 {0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13619 &EmulateInstructionARM::EmulateLDRSHRegister,
13620 "ldrsh<c> <Rt>,[<Rn>,<Rm>]"},
13621 {0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13622 &EmulateInstructionARM::EmulateLDRSHRegister,
13623 "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13624 {0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13625 &EmulateInstructionARM::EmulateLDRDImmediate,
13626 "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
13627 {0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13628 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13629 {0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13630 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13631 {0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13632 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13633 {0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13634 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
13635 {0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13636 &EmulateInstructionARM::EmulateVLD1Multiple,
13637 "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
13638 {0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13639 &EmulateInstructionARM::EmulateVLD1Single,
13640 "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
13641 {0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13642 &EmulateInstructionARM::EmulateVLD1SingleAll,
13643 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13645 // Store instructions
13646 {0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13647 &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"},
13648 {0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13649 &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>"},
13650 {0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13651 &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"},
13652 {0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13653 &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]"},
13654 {0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,
13655 &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]"},
13656 {0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13657 &EmulateInstructionARM::EmulateSTRThumb,
13658 "str<c>.w <Rt>, [<Rn>,#<imm12>]"},
13659 {0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13660 &EmulateInstructionARM::EmulateSTRThumb,
13661 "str<c> <Rt>, [<Rn>,#+/-<imm8>]"},
13662 {0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13663 &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]"},
13664 {0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13665 &EmulateInstructionARM::EmulateSTRRegister,
13666 "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]"},
13667 {0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13668 &EmulateInstructionARM::EmulateSTRBThumb,
13669 "strb<c> <Rt>, [<Rn>, #<imm5>]"},
13670 {0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13671 &EmulateInstructionARM::EmulateSTRBThumb,
13672 "strb<c>.w <Rt>, [<Rn>, #<imm12>]"},
13673 {0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13674 &EmulateInstructionARM::EmulateSTRBThumb,
13675 "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}"},
13676 {0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13677 &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]"},
13678 {0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13679 &EmulateInstructionARM::EmulateSTRHRegister,
13680 "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13681 {0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13682 &EmulateInstructionARM::EmulateSTREX,
13683 "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]"},
13684 {0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13685 &EmulateInstructionARM::EmulateSTRDImm,
13686 "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
13687 {0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13688 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
13689 {0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13690 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
13691 {0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13692 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13693 {0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13694 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
13695 {0xffb00000, 0xf9000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13696 &EmulateInstructionARM::EmulateVST1Multiple,
13697 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13698 {0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13699 &EmulateInstructionARM::EmulateVST1Single,
13700 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13702 // Other instructions
13703 {0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13704 &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>"},
13705 {0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32,
13706 &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}"},
13707 {0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13708 &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>"},
13709 {0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13710 &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}"},
13711 {0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13712 &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>"},
13713 {0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13714 &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}"},
13715 {0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13716 &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>"},
13717 {0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13718 &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}"},
13721 const size_t k_num_thumb_opcodes = std::size(g_thumb_opcodes);
13722 for (size_t i = 0; i < k_num_thumb_opcodes; ++i) {
13723 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value &&
13724 (g_thumb_opcodes[i].variants & arm_isa) != 0)
13725 return &g_thumb_opcodes[i];
13727 return nullptr;
13730 bool EmulateInstructionARM::SetArchitecture(const ArchSpec &arch) {
13731 m_arch = arch;
13732 m_arm_isa = 0;
13733 llvm::StringRef arch_cstr = arch.GetArchitectureName();
13734 if (arch_cstr.equals_insensitive("armv4t"))
13735 m_arm_isa = ARMv4T;
13736 else if (arch_cstr.equals_insensitive("armv5tej"))
13737 m_arm_isa = ARMv5TEJ;
13738 else if (arch_cstr.equals_insensitive("armv5te"))
13739 m_arm_isa = ARMv5TE;
13740 else if (arch_cstr.equals_insensitive("armv5t"))
13741 m_arm_isa = ARMv5T;
13742 else if (arch_cstr.equals_insensitive("armv6k"))
13743 m_arm_isa = ARMv6K;
13744 else if (arch_cstr.equals_insensitive("armv6t2"))
13745 m_arm_isa = ARMv6T2;
13746 else if (arch_cstr.equals_insensitive("armv7s"))
13747 m_arm_isa = ARMv7S;
13748 else if (arch_cstr.equals_insensitive("arm"))
13749 m_arm_isa = ARMvAll;
13750 else if (arch_cstr.equals_insensitive("thumb"))
13751 m_arm_isa = ARMvAll;
13752 else if (arch_cstr.starts_with_insensitive("armv4"))
13753 m_arm_isa = ARMv4;
13754 else if (arch_cstr.starts_with_insensitive("armv6"))
13755 m_arm_isa = ARMv6;
13756 else if (arch_cstr.starts_with_insensitive("armv7"))
13757 m_arm_isa = ARMv7;
13758 else if (arch_cstr.starts_with_insensitive("armv8"))
13759 m_arm_isa = ARMv8;
13760 return m_arm_isa != 0;
13763 bool EmulateInstructionARM::SetInstruction(const Opcode &insn_opcode,
13764 const Address &inst_addr,
13765 Target *target) {
13766 if (EmulateInstruction::SetInstruction(insn_opcode, inst_addr, target)) {
13767 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb ||
13768 m_arch.IsAlwaysThumbInstructions())
13769 m_opcode_mode = eModeThumb;
13770 else {
13771 AddressClass addr_class = inst_addr.GetAddressClass();
13773 if ((addr_class == AddressClass::eCode) ||
13774 (addr_class == AddressClass::eUnknown))
13775 m_opcode_mode = eModeARM;
13776 else if (addr_class == AddressClass::eCodeAlternateISA)
13777 m_opcode_mode = eModeThumb;
13778 else
13779 return false;
13781 if (m_opcode_mode == eModeThumb || m_arch.IsAlwaysThumbInstructions())
13782 m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T;
13783 else
13784 m_opcode_cpsr = CPSR_MODE_USR;
13785 return true;
13787 return false;
13790 bool EmulateInstructionARM::ReadInstruction() {
13791 bool success = false;
13792 m_opcode_cpsr = ReadRegisterUnsigned(eRegisterKindGeneric,
13793 LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
13794 if (success) {
13795 addr_t pc =
13796 ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
13797 LLDB_INVALID_ADDRESS, &success);
13798 if (success) {
13799 Context read_inst_context;
13800 read_inst_context.type = eContextReadOpcode;
13801 read_inst_context.SetNoArgs();
13803 if ((m_opcode_cpsr & MASK_CPSR_T) || m_arch.IsAlwaysThumbInstructions()) {
13804 m_opcode_mode = eModeThumb;
13805 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
13807 if (success) {
13808 if ((thumb_opcode & 0xe000) != 0xe000 ||
13809 ((thumb_opcode & 0x1800u) == 0)) {
13810 m_opcode.SetOpcode16(thumb_opcode, GetByteOrder());
13811 } else {
13812 m_opcode.SetOpcode32(
13813 (thumb_opcode << 16) |
13814 MemARead(read_inst_context, pc + 2, 2, 0, &success),
13815 GetByteOrder());
13818 } else {
13819 m_opcode_mode = eModeARM;
13820 m_opcode.SetOpcode32(MemARead(read_inst_context, pc, 4, 0, &success),
13821 GetByteOrder());
13824 if (!m_ignore_conditions) {
13825 // If we are not ignoreing the conditions then init the it session from
13826 // the current value of cpsr.
13827 uint32_t it = (Bits32(m_opcode_cpsr, 15, 10) << 2) |
13828 Bits32(m_opcode_cpsr, 26, 25);
13829 if (it != 0)
13830 m_it_session.InitIT(it);
13834 if (!success) {
13835 m_opcode_mode = eModeInvalid;
13836 m_addr = LLDB_INVALID_ADDRESS;
13838 return success;
13841 uint32_t EmulateInstructionARM::ArchVersion() { return m_arm_isa; }
13843 bool EmulateInstructionARM::ConditionPassed(const uint32_t opcode) {
13844 // If we are ignoring conditions, then always return true. this allows us to
13845 // iterate over disassembly code and still emulate an instruction even if we
13846 // don't have all the right bits set in the CPSR register...
13847 if (m_ignore_conditions)
13848 return true;
13850 const uint32_t cond = CurrentCond(opcode);
13851 if (cond == UINT32_MAX)
13852 return false;
13854 bool result = false;
13855 switch (UnsignedBits(cond, 3, 1)) {
13856 case 0:
13857 if (m_opcode_cpsr == 0)
13858 result = true;
13859 else
13860 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;
13861 break;
13862 case 1:
13863 if (m_opcode_cpsr == 0)
13864 result = true;
13865 else
13866 result = (m_opcode_cpsr & MASK_CPSR_C) != 0;
13867 break;
13868 case 2:
13869 if (m_opcode_cpsr == 0)
13870 result = true;
13871 else
13872 result = (m_opcode_cpsr & MASK_CPSR_N) != 0;
13873 break;
13874 case 3:
13875 if (m_opcode_cpsr == 0)
13876 result = true;
13877 else
13878 result = (m_opcode_cpsr & MASK_CPSR_V) != 0;
13879 break;
13880 case 4:
13881 if (m_opcode_cpsr == 0)
13882 result = true;
13883 else
13884 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) &&
13885 ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
13886 break;
13887 case 5:
13888 if (m_opcode_cpsr == 0)
13889 result = true;
13890 else {
13891 bool n = (m_opcode_cpsr & MASK_CPSR_N);
13892 bool v = (m_opcode_cpsr & MASK_CPSR_V);
13893 result = n == v;
13895 break;
13896 case 6:
13897 if (m_opcode_cpsr == 0)
13898 result = true;
13899 else {
13900 bool n = (m_opcode_cpsr & MASK_CPSR_N);
13901 bool v = (m_opcode_cpsr & MASK_CPSR_V);
13902 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
13904 break;
13905 case 7:
13906 // Always execute (cond == 0b1110, or the special 0b1111 which gives
13907 // opcodes different meanings, but always means execution happens.
13908 return true;
13911 if (cond & 1)
13912 result = !result;
13913 return result;
13916 uint32_t EmulateInstructionARM::CurrentCond(const uint32_t opcode) {
13917 switch (m_opcode_mode) {
13918 case eModeInvalid:
13919 break;
13921 case eModeARM:
13922 return UnsignedBits(opcode, 31, 28);
13924 case eModeThumb:
13925 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
13926 // 'cond' field of the encoding.
13928 const uint32_t byte_size = m_opcode.GetByteSize();
13929 if (byte_size == 2) {
13930 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 8) != 0x0f)
13931 return Bits32(opcode, 11, 8);
13932 } else if (byte_size == 4) {
13933 if (Bits32(opcode, 31, 27) == 0x1e && Bits32(opcode, 15, 14) == 0x02 &&
13934 Bits32(opcode, 12, 12) == 0x00 && Bits32(opcode, 25, 22) <= 0x0d) {
13935 return Bits32(opcode, 25, 22);
13937 } else
13938 // We have an invalid thumb instruction, let's bail out.
13939 break;
13941 return m_it_session.GetCond();
13944 return UINT32_MAX; // Return invalid value
13947 bool EmulateInstructionARM::InITBlock() {
13948 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
13951 bool EmulateInstructionARM::LastInITBlock() {
13952 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
13955 bool EmulateInstructionARM::BadMode(uint32_t mode) {
13957 switch (mode) {
13958 case 16:
13959 return false; // '10000'
13960 case 17:
13961 return false; // '10001'
13962 case 18:
13963 return false; // '10010'
13964 case 19:
13965 return false; // '10011'
13966 case 22:
13967 return false; // '10110'
13968 case 23:
13969 return false; // '10111'
13970 case 27:
13971 return false; // '11011'
13972 case 31:
13973 return false; // '11111'
13974 default:
13975 return true;
13977 return true;
13980 bool EmulateInstructionARM::CurrentModeIsPrivileged() {
13981 uint32_t mode = Bits32(m_opcode_cpsr, 4, 0);
13983 if (BadMode(mode))
13984 return false;
13986 if (mode == 16)
13987 return false;
13989 return true;
13992 void EmulateInstructionARM::CPSRWriteByInstr(uint32_t value, uint32_t bytemask,
13993 bool affect_execstate) {
13994 bool privileged = CurrentModeIsPrivileged();
13996 uint32_t tmp_cpsr = Bits32(m_opcode_cpsr, 23, 20) << 20;
13998 if (BitIsSet(bytemask, 3)) {
13999 tmp_cpsr = tmp_cpsr | (Bits32(value, 31, 27) << 27);
14000 if (affect_execstate)
14001 tmp_cpsr = tmp_cpsr | (Bits32(value, 26, 24) << 24);
14004 if (BitIsSet(bytemask, 2)) {
14005 tmp_cpsr = tmp_cpsr | (Bits32(value, 19, 16) << 16);
14008 if (BitIsSet(bytemask, 1)) {
14009 if (affect_execstate)
14010 tmp_cpsr = tmp_cpsr | (Bits32(value, 15, 10) << 10);
14011 tmp_cpsr = tmp_cpsr | (Bit32(value, 9) << 9);
14012 if (privileged)
14013 tmp_cpsr = tmp_cpsr | (Bit32(value, 8) << 8);
14016 if (BitIsSet(bytemask, 0)) {
14017 if (privileged)
14018 tmp_cpsr = tmp_cpsr | (Bits32(value, 7, 6) << 6);
14019 if (affect_execstate)
14020 tmp_cpsr = tmp_cpsr | (Bit32(value, 5) << 5);
14021 if (privileged)
14022 tmp_cpsr = tmp_cpsr | Bits32(value, 4, 0);
14025 m_opcode_cpsr = tmp_cpsr;
14028 bool EmulateInstructionARM::BranchWritePC(const Context &context,
14029 uint32_t addr) {
14030 addr_t target;
14032 // Check the current instruction set.
14033 if (CurrentInstrSet() == eModeARM)
14034 target = addr & 0xfffffffc;
14035 else
14036 target = addr & 0xfffffffe;
14038 return WriteRegisterUnsigned(context, eRegisterKindGeneric,
14039 LLDB_REGNUM_GENERIC_PC, target);
14042 // As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by
14043 // inspecting addr.
14044 bool EmulateInstructionARM::BXWritePC(Context &context, uint32_t addr) {
14045 addr_t target;
14046 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
14047 // we want to record it and issue a WriteRegister callback so the clients can
14048 // track the mode changes accordingly.
14049 bool cpsr_changed = false;
14051 if (BitIsSet(addr, 0)) {
14052 if (CurrentInstrSet() != eModeThumb) {
14053 SelectInstrSet(eModeThumb);
14054 cpsr_changed = true;
14056 target = addr & 0xfffffffe;
14057 context.SetISA(eModeThumb);
14058 } else if (BitIsClear(addr, 1)) {
14059 if (CurrentInstrSet() != eModeARM) {
14060 SelectInstrSet(eModeARM);
14061 cpsr_changed = true;
14063 target = addr & 0xfffffffc;
14064 context.SetISA(eModeARM);
14065 } else
14066 return false; // address<1:0> == '10' => UNPREDICTABLE
14068 if (cpsr_changed) {
14069 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
14070 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
14071 return false;
14073 return WriteRegisterUnsigned(context, eRegisterKindGeneric,
14074 LLDB_REGNUM_GENERIC_PC, target);
14077 // Dispatches to either BXWritePC or BranchWritePC based on architecture
14078 // versions.
14079 bool EmulateInstructionARM::LoadWritePC(Context &context, uint32_t addr) {
14080 if (ArchVersion() >= ARMv5T)
14081 return BXWritePC(context, addr);
14082 else
14083 return BranchWritePC((const Context)context, addr);
14086 // Dispatches to either BXWritePC or BranchWritePC based on architecture
14087 // versions and current instruction set.
14088 bool EmulateInstructionARM::ALUWritePC(Context &context, uint32_t addr) {
14089 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
14090 return BXWritePC(context, addr);
14091 else
14092 return BranchWritePC((const Context)context, addr);
14095 EmulateInstructionARM::Mode EmulateInstructionARM::CurrentInstrSet() {
14096 return m_opcode_mode;
14099 // Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
14100 // ReadInstruction() is performed. This function has a side effect of updating
14101 // the m_new_inst_cpsr member variable if necessary.
14102 bool EmulateInstructionARM::SelectInstrSet(Mode arm_or_thumb) {
14103 m_new_inst_cpsr = m_opcode_cpsr;
14104 switch (arm_or_thumb) {
14105 default:
14106 return false;
14107 case eModeARM:
14108 // Clear the T bit.
14109 m_new_inst_cpsr &= ~MASK_CPSR_T;
14110 break;
14111 case eModeThumb:
14112 // Set the T bit.
14113 m_new_inst_cpsr |= MASK_CPSR_T;
14114 break;
14116 return true;
14119 // This function returns TRUE if the processor currently provides support for
14120 // unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
14121 // controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
14122 bool EmulateInstructionARM::UnalignedSupport() {
14123 return (ArchVersion() >= ARMv7);
14126 // The main addition and subtraction instructions can produce status
14127 // information about both unsigned carry and signed overflow conditions. This
14128 // status information can be used to synthesize multi-word additions and
14129 // subtractions.
14130 EmulateInstructionARM::AddWithCarryResult
14131 EmulateInstructionARM::AddWithCarry(uint32_t x, uint32_t y, uint8_t carry_in) {
14132 uint32_t result;
14133 uint8_t carry_out;
14134 uint8_t overflow;
14136 uint64_t unsigned_sum = x + y + carry_in;
14137 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
14139 result = UnsignedBits(unsigned_sum, 31, 0);
14140 // carry_out = (result == unsigned_sum ? 0 : 1);
14141 overflow = ((int32_t)result == signed_sum ? 0 : 1);
14143 if (carry_in)
14144 carry_out = ((int32_t)x >= (int32_t)(~y)) ? 1 : 0;
14145 else
14146 carry_out = ((int32_t)x > (int32_t)y) ? 1 : 0;
14148 AddWithCarryResult res = {result, carry_out, overflow};
14149 return res;
14152 uint32_t EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success) {
14153 lldb::RegisterKind reg_kind;
14154 uint32_t reg_num;
14155 switch (num) {
14156 case SP_REG:
14157 reg_kind = eRegisterKindGeneric;
14158 reg_num = LLDB_REGNUM_GENERIC_SP;
14159 break;
14160 case LR_REG:
14161 reg_kind = eRegisterKindGeneric;
14162 reg_num = LLDB_REGNUM_GENERIC_RA;
14163 break;
14164 case PC_REG:
14165 reg_kind = eRegisterKindGeneric;
14166 reg_num = LLDB_REGNUM_GENERIC_PC;
14167 break;
14168 default:
14169 if (num < SP_REG) {
14170 reg_kind = eRegisterKindDWARF;
14171 reg_num = dwarf_r0 + num;
14172 } else {
14173 // assert(0 && "Invalid register number");
14174 *success = false;
14175 return UINT32_MAX;
14177 break;
14180 // Read our register.
14181 uint32_t val = ReadRegisterUnsigned(reg_kind, reg_num, 0, success);
14183 // When executing an ARM instruction , PC reads as the address of the current
14184 // instruction plus 8. When executing a Thumb instruction , PC reads as the
14185 // address of the current instruction plus 4.
14186 if (num == 15) {
14187 if (CurrentInstrSet() == eModeARM)
14188 val += 8;
14189 else
14190 val += 4;
14193 return val;
14196 // Write the result to the ARM core register Rd, and optionally update the
14197 // condition flags based on the result.
14199 // This helper method tries to encapsulate the following pseudocode from the
14200 // ARM Architecture Reference Manual:
14202 // if d == 15 then // Can only occur for encoding A1
14203 // ALUWritePC(result); // setflags is always FALSE here
14204 // else
14205 // R[d] = result;
14206 // if setflags then
14207 // APSR.N = result<31>;
14208 // APSR.Z = IsZeroBit(result);
14209 // APSR.C = carry;
14210 // // APSR.V unchanged
14212 // In the above case, the API client does not pass in the overflow arg, which
14213 // defaults to ~0u.
14214 bool EmulateInstructionARM::WriteCoreRegOptionalFlags(
14215 Context &context, const uint32_t result, const uint32_t Rd, bool setflags,
14216 const uint32_t carry, const uint32_t overflow) {
14217 if (Rd == 15) {
14218 if (!ALUWritePC(context, result))
14219 return false;
14220 } else {
14221 lldb::RegisterKind reg_kind;
14222 uint32_t reg_num;
14223 switch (Rd) {
14224 case SP_REG:
14225 reg_kind = eRegisterKindGeneric;
14226 reg_num = LLDB_REGNUM_GENERIC_SP;
14227 break;
14228 case LR_REG:
14229 reg_kind = eRegisterKindGeneric;
14230 reg_num = LLDB_REGNUM_GENERIC_RA;
14231 break;
14232 default:
14233 reg_kind = eRegisterKindDWARF;
14234 reg_num = dwarf_r0 + Rd;
14236 if (!WriteRegisterUnsigned(context, reg_kind, reg_num, result))
14237 return false;
14238 if (setflags)
14239 return WriteFlags(context, result, carry, overflow);
14241 return true;
14244 // This helper method tries to encapsulate the following pseudocode from the
14245 // ARM Architecture Reference Manual:
14247 // APSR.N = result<31>;
14248 // APSR.Z = IsZeroBit(result);
14249 // APSR.C = carry;
14250 // APSR.V = overflow
14252 // Default arguments can be specified for carry and overflow parameters, which
14253 // means not to update the respective flags.
14254 bool EmulateInstructionARM::WriteFlags(Context &context, const uint32_t result,
14255 const uint32_t carry,
14256 const uint32_t overflow) {
14257 m_new_inst_cpsr = m_opcode_cpsr;
14258 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
14259 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
14260 if (carry != ~0u)
14261 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
14262 if (overflow != ~0u)
14263 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
14264 if (m_new_inst_cpsr != m_opcode_cpsr) {
14265 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
14266 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
14267 return false;
14269 return true;
14272 bool EmulateInstructionARM::EvaluateInstruction(uint32_t evaluate_options) {
14273 ARMOpcode *opcode_data = nullptr;
14275 if (m_opcode_mode == eModeThumb)
14276 opcode_data =
14277 GetThumbOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa);
14278 else if (m_opcode_mode == eModeARM)
14279 opcode_data = GetARMOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa);
14281 const bool auto_advance_pc =
14282 evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
14283 m_ignore_conditions =
14284 evaluate_options & eEmulateInstructionOptionIgnoreConditions;
14286 bool success = false;
14287 if (m_opcode_cpsr == 0 || !m_ignore_conditions) {
14288 m_opcode_cpsr =
14289 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success);
14292 // Only return false if we are unable to read the CPSR if we care about
14293 // conditions
14294 if (!success && !m_ignore_conditions)
14295 return false;
14297 uint32_t orig_pc_value = 0;
14298 if (auto_advance_pc) {
14299 orig_pc_value =
14300 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success);
14301 if (!success)
14302 return false;
14305 // Call the Emulate... function if we managed to decode the opcode.
14306 if (opcode_data) {
14307 success = (this->*opcode_data->callback)(m_opcode.GetOpcode32(),
14308 opcode_data->encoding);
14309 if (!success)
14310 return false;
14313 // Advance the ITSTATE bits to their values for the next instruction if we
14314 // haven't just executed an IT instruction what initialized it.
14315 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock() &&
14316 (opcode_data == nullptr ||
14317 opcode_data->callback != &EmulateInstructionARM::EmulateIT))
14318 m_it_session.ITAdvance();
14320 if (auto_advance_pc) {
14321 uint32_t after_pc_value =
14322 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success);
14323 if (!success)
14324 return false;
14326 if (after_pc_value == orig_pc_value) {
14327 after_pc_value += m_opcode.GetByteSize();
14329 EmulateInstruction::Context context;
14330 context.type = eContextAdvancePC;
14331 context.SetNoArgs();
14332 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc,
14333 after_pc_value))
14334 return false;
14337 return true;
14340 EmulateInstruction::InstructionCondition
14341 EmulateInstructionARM::GetInstructionCondition() {
14342 const uint32_t cond = CurrentCond(m_opcode.GetOpcode32());
14343 if (cond == 0xe || cond == 0xf || cond == UINT32_MAX)
14344 return EmulateInstruction::UnconditionalCondition;
14345 return cond;
14348 bool EmulateInstructionARM::TestEmulation(Stream &out_stream, ArchSpec &arch,
14349 OptionValueDictionary *test_data) {
14350 if (!test_data) {
14351 out_stream.Printf("TestEmulation: Missing test data.\n");
14352 return false;
14355 static constexpr llvm::StringLiteral opcode_key("opcode");
14356 static constexpr llvm::StringLiteral before_key("before_state");
14357 static constexpr llvm::StringLiteral after_key("after_state");
14359 OptionValueSP value_sp = test_data->GetValueForKey(opcode_key);
14361 uint32_t test_opcode;
14362 if ((value_sp.get() == nullptr) ||
14363 (value_sp->GetType() != OptionValue::eTypeUInt64)) {
14364 out_stream.Printf("TestEmulation: Error reading opcode from test file.\n");
14365 return false;
14367 test_opcode = value_sp->GetValueAs<uint64_t>().value_or(0);
14369 if (arch.GetTriple().getArch() == llvm::Triple::thumb ||
14370 arch.IsAlwaysThumbInstructions()) {
14371 m_opcode_mode = eModeThumb;
14372 if (test_opcode < 0x10000)
14373 m_opcode.SetOpcode16(test_opcode, endian::InlHostByteOrder());
14374 else
14375 m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder());
14376 } else if (arch.GetTriple().getArch() == llvm::Triple::arm) {
14377 m_opcode_mode = eModeARM;
14378 m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder());
14379 } else {
14380 out_stream.Printf("TestEmulation: Invalid arch.\n");
14381 return false;
14384 EmulationStateARM before_state;
14385 EmulationStateARM after_state;
14387 value_sp = test_data->GetValueForKey(before_key);
14388 if ((value_sp.get() == nullptr) ||
14389 (value_sp->GetType() != OptionValue::eTypeDictionary)) {
14390 out_stream.Printf("TestEmulation: Failed to find 'before' state.\n");
14391 return false;
14394 OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary();
14395 if (!before_state.LoadStateFromDictionary(state_dictionary)) {
14396 out_stream.Printf("TestEmulation: Failed loading 'before' state.\n");
14397 return false;
14400 value_sp = test_data->GetValueForKey(after_key);
14401 if ((value_sp.get() == nullptr) ||
14402 (value_sp->GetType() != OptionValue::eTypeDictionary)) {
14403 out_stream.Printf("TestEmulation: Failed to find 'after' state.\n");
14404 return false;
14407 state_dictionary = value_sp->GetAsDictionary();
14408 if (!after_state.LoadStateFromDictionary(state_dictionary)) {
14409 out_stream.Printf("TestEmulation: Failed loading 'after' state.\n");
14410 return false;
14413 SetBaton((void *)&before_state);
14414 SetCallbacks(&EmulationStateARM::ReadPseudoMemory,
14415 &EmulationStateARM::WritePseudoMemory,
14416 &EmulationStateARM::ReadPseudoRegister,
14417 &EmulationStateARM::WritePseudoRegister);
14419 bool success = EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC);
14420 if (!success) {
14421 out_stream.Printf("TestEmulation: EvaluateInstruction() failed.\n");
14422 return false;
14425 success = before_state.CompareState(after_state, out_stream);
14426 if (!success)
14427 out_stream.Printf("TestEmulation: State after emulation does not match "
14428 "'after' state.\n");
14430 return success;
14434 // const char *
14435 // EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)
14437 // if (reg_kind == eRegisterKindGeneric)
14438 // {
14439 // switch (reg_num)
14440 // {
14441 // case LLDB_REGNUM_GENERIC_PC: return "pc";
14442 // case LLDB_REGNUM_GENERIC_SP: return "sp";
14443 // case LLDB_REGNUM_GENERIC_FP: return "fp";
14444 // case LLDB_REGNUM_GENERIC_RA: return "lr";
14445 // case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";
14446 // default: return NULL;
14447 // }
14448 // }
14449 // else if (reg_kind == eRegisterKindDWARF)
14450 // {
14451 // return GetARMDWARFRegisterName (reg_num);
14452 // }
14453 // return NULL;
14456 bool EmulateInstructionARM::CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) {
14457 unwind_plan.Clear();
14458 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
14460 UnwindPlan::RowSP row(new UnwindPlan::Row);
14462 // Our previous Call Frame Address is the stack pointer
14463 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp, 0);
14465 unwind_plan.AppendRow(row);
14466 unwind_plan.SetSourceName("EmulateInstructionARM");
14467 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
14468 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
14469 unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
14470 unwind_plan.SetReturnAddressRegister(dwarf_lr);
14471 return true;