LLDB mainline
EmulateInstructionARM.cpp
Go to the documentation of this file.
1//===-- EmulateInstructionARM.cpp -----------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include <cstdlib>
10#include <optional>
11
13#include "EmulationStateARM.h"
14#include "lldb/Core/Address.h"
16#include "lldb/Host/PosixApi.h"
21#include "lldb/Utility/Stream.h"
22
26
27#include "llvm/ADT/STLExtras.h"
28#include "llvm/Support/MathExtras.h"
29
30using namespace lldb;
31using namespace lldb_private;
32
34
35// Convenient macro definitions.
36#define APSR_C Bit32(m_opcode_cpsr, CPSR_C_POS)
37#define APSR_V Bit32(m_opcode_cpsr, CPSR_V_POS)
38
39#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
40
41//
42// ITSession implementation
43//
44
45static std::optional<RegisterInfo> GetARMDWARFRegisterInfo(unsigned reg_num) {
46 RegisterInfo reg_info;
47 ::memset(&reg_info, 0, sizeof(RegisterInfo));
48 ::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
49
50 if (reg_num >= dwarf_q0 && reg_num <= dwarf_q15) {
51 reg_info.byte_size = 16;
53 reg_info.encoding = eEncodingVector;
54 }
55
56 if (reg_num >= dwarf_d0 && reg_num <= dwarf_d31) {
57 reg_info.byte_size = 8;
58 reg_info.format = eFormatFloat;
59 reg_info.encoding = eEncodingIEEE754;
60 } else if (reg_num >= dwarf_s0 && reg_num <= dwarf_s31) {
61 reg_info.byte_size = 4;
62 reg_info.format = eFormatFloat;
63 reg_info.encoding = eEncodingIEEE754;
64 } else if (reg_num >= dwarf_f0 && reg_num <= dwarf_f7) {
65 reg_info.byte_size = 12;
66 reg_info.format = eFormatFloat;
67 reg_info.encoding = eEncodingIEEE754;
68 } else {
69 reg_info.byte_size = 4;
70 reg_info.format = eFormatHex;
71 reg_info.encoding = eEncodingUint;
72 }
73
74 reg_info.kinds[eRegisterKindDWARF] = reg_num;
75
76 switch (reg_num) {
77 case dwarf_r0:
78 reg_info.name = "r0";
79 break;
80 case dwarf_r1:
81 reg_info.name = "r1";
82 break;
83 case dwarf_r2:
84 reg_info.name = "r2";
85 break;
86 case dwarf_r3:
87 reg_info.name = "r3";
88 break;
89 case dwarf_r4:
90 reg_info.name = "r4";
91 break;
92 case dwarf_r5:
93 reg_info.name = "r5";
94 break;
95 case dwarf_r6:
96 reg_info.name = "r6";
97 break;
98 case dwarf_r7:
99 reg_info.name = "r7";
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";
121 break;
122 case dwarf_lr:
123 reg_info.name = "lr";
124 reg_info.alt_name = "r14";
126 break;
127 case dwarf_pc:
128 reg_info.name = "pc";
129 reg_info.alt_name = "r15";
131 break;
132 case dwarf_cpsr:
133 reg_info.name = "cpsr";
135 break;
136
137 case dwarf_s0:
138 reg_info.name = "s0";
139 break;
140 case dwarf_s1:
141 reg_info.name = "s1";
142 break;
143 case dwarf_s2:
144 reg_info.name = "s2";
145 break;
146 case dwarf_s3:
147 reg_info.name = "s3";
148 break;
149 case dwarf_s4:
150 reg_info.name = "s4";
151 break;
152 case dwarf_s5:
153 reg_info.name = "s5";
154 break;
155 case dwarf_s6:
156 reg_info.name = "s6";
157 break;
158 case dwarf_s7:
159 reg_info.name = "s7";
160 break;
161 case dwarf_s8:
162 reg_info.name = "s8";
163 break;
164 case dwarf_s9:
165 reg_info.name = "s9";
166 break;
167 case dwarf_s10:
168 reg_info.name = "s10";
169 break;
170 case dwarf_s11:
171 reg_info.name = "s11";
172 break;
173 case dwarf_s12:
174 reg_info.name = "s12";
175 break;
176 case dwarf_s13:
177 reg_info.name = "s13";
178 break;
179 case dwarf_s14:
180 reg_info.name = "s14";
181 break;
182 case dwarf_s15:
183 reg_info.name = "s15";
184 break;
185 case dwarf_s16:
186 reg_info.name = "s16";
187 break;
188 case dwarf_s17:
189 reg_info.name = "s17";
190 break;
191 case dwarf_s18:
192 reg_info.name = "s18";
193 break;
194 case dwarf_s19:
195 reg_info.name = "s19";
196 break;
197 case dwarf_s20:
198 reg_info.name = "s20";
199 break;
200 case dwarf_s21:
201 reg_info.name = "s21";
202 break;
203 case dwarf_s22:
204 reg_info.name = "s22";
205 break;
206 case dwarf_s23:
207 reg_info.name = "s23";
208 break;
209 case dwarf_s24:
210 reg_info.name = "s24";
211 break;
212 case dwarf_s25:
213 reg_info.name = "s25";
214 break;
215 case dwarf_s26:
216 reg_info.name = "s26";
217 break;
218 case dwarf_s27:
219 reg_info.name = "s27";
220 break;
221 case dwarf_s28:
222 reg_info.name = "s28";
223 break;
224 case dwarf_s29:
225 reg_info.name = "s29";
226 break;
227 case dwarf_s30:
228 reg_info.name = "s30";
229 break;
230 case dwarf_s31:
231 reg_info.name = "s31";
232 break;
233
234 // FPA Registers 0-7
235 case dwarf_f0:
236 reg_info.name = "f0";
237 break;
238 case dwarf_f1:
239 reg_info.name = "f1";
240 break;
241 case dwarf_f2:
242 reg_info.name = "f2";
243 break;
244 case dwarf_f3:
245 reg_info.name = "f3";
246 break;
247 case dwarf_f4:
248 reg_info.name = "f4";
249 break;
250 case dwarf_f5:
251 reg_info.name = "f5";
252 break;
253 case dwarf_f6:
254 reg_info.name = "f6";
255 break;
256 case dwarf_f7:
257 reg_info.name = "f7";
258 break;
259
260 // Intel wireless MMX general purpose registers 0 - 7 XScale accumulator
261 // register 0 - 7 (they do overlap with wCGR0 - wCGR7)
262 case dwarf_wCGR0:
263 reg_info.name = "wCGR0/ACC0";
264 break;
265 case dwarf_wCGR1:
266 reg_info.name = "wCGR1/ACC1";
267 break;
268 case dwarf_wCGR2:
269 reg_info.name = "wCGR2/ACC2";
270 break;
271 case dwarf_wCGR3:
272 reg_info.name = "wCGR3/ACC3";
273 break;
274 case dwarf_wCGR4:
275 reg_info.name = "wCGR4/ACC4";
276 break;
277 case dwarf_wCGR5:
278 reg_info.name = "wCGR5/ACC5";
279 break;
280 case dwarf_wCGR6:
281 reg_info.name = "wCGR6/ACC6";
282 break;
283 case dwarf_wCGR7:
284 reg_info.name = "wCGR7/ACC7";
285 break;
286
287 // Intel wireless MMX data registers 0 - 15
288 case dwarf_wR0:
289 reg_info.name = "wR0";
290 break;
291 case dwarf_wR1:
292 reg_info.name = "wR1";
293 break;
294 case dwarf_wR2:
295 reg_info.name = "wR2";
296 break;
297 case dwarf_wR3:
298 reg_info.name = "wR3";
299 break;
300 case dwarf_wR4:
301 reg_info.name = "wR4";
302 break;
303 case dwarf_wR5:
304 reg_info.name = "wR5";
305 break;
306 case dwarf_wR6:
307 reg_info.name = "wR6";
308 break;
309 case dwarf_wR7:
310 reg_info.name = "wR7";
311 break;
312 case dwarf_wR8:
313 reg_info.name = "wR8";
314 break;
315 case dwarf_wR9:
316 reg_info.name = "wR9";
317 break;
318 case dwarf_wR10:
319 reg_info.name = "wR10";
320 break;
321 case dwarf_wR11:
322 reg_info.name = "wR11";
323 break;
324 case dwarf_wR12:
325 reg_info.name = "wR12";
326 break;
327 case dwarf_wR13:
328 reg_info.name = "wR13";
329 break;
330 case dwarf_wR14:
331 reg_info.name = "wR14";
332 break;
333 case dwarf_wR15:
334 reg_info.name = "wR15";
335 break;
336
337 case dwarf_spsr:
338 reg_info.name = "spsr";
339 break;
340 case dwarf_spsr_fiq:
341 reg_info.name = "spsr_fiq";
342 break;
343 case dwarf_spsr_irq:
344 reg_info.name = "spsr_irq";
345 break;
346 case dwarf_spsr_abt:
347 reg_info.name = "spsr_abt";
348 break;
349 case dwarf_spsr_und:
350 reg_info.name = "spsr_und";
351 break;
352 case dwarf_spsr_svc:
353 reg_info.name = "spsr_svc";
354 break;
355
356 case dwarf_r8_usr:
357 reg_info.name = "r8_usr";
358 break;
359 case dwarf_r9_usr:
360 reg_info.name = "r9_usr";
361 break;
362 case dwarf_r10_usr:
363 reg_info.name = "r10_usr";
364 break;
365 case dwarf_r11_usr:
366 reg_info.name = "r11_usr";
367 break;
368 case dwarf_r12_usr:
369 reg_info.name = "r12_usr";
370 break;
371 case dwarf_r13_usr:
372 reg_info.name = "r13_usr";
373 break;
374 case dwarf_r14_usr:
375 reg_info.name = "r14_usr";
376 break;
377 case dwarf_r8_fiq:
378 reg_info.name = "r8_fiq";
379 break;
380 case dwarf_r9_fiq:
381 reg_info.name = "r9_fiq";
382 break;
383 case dwarf_r10_fiq:
384 reg_info.name = "r10_fiq";
385 break;
386 case dwarf_r11_fiq:
387 reg_info.name = "r11_fiq";
388 break;
389 case dwarf_r12_fiq:
390 reg_info.name = "r12_fiq";
391 break;
392 case dwarf_r13_fiq:
393 reg_info.name = "r13_fiq";
394 break;
395 case dwarf_r14_fiq:
396 reg_info.name = "r14_fiq";
397 break;
398 case dwarf_r13_irq:
399 reg_info.name = "r13_irq";
400 break;
401 case dwarf_r14_irq:
402 reg_info.name = "r14_irq";
403 break;
404 case dwarf_r13_abt:
405 reg_info.name = "r13_abt";
406 break;
407 case dwarf_r14_abt:
408 reg_info.name = "r14_abt";
409 break;
410 case dwarf_r13_und:
411 reg_info.name = "r13_und";
412 break;
413 case dwarf_r14_und:
414 reg_info.name = "r14_und";
415 break;
416 case dwarf_r13_svc:
417 reg_info.name = "r13_svc";
418 break;
419 case dwarf_r14_svc:
420 reg_info.name = "r14_svc";
421 break;
422
423 // Intel wireless MMX control register in co-processor 0 - 7
424 case dwarf_wC0:
425 reg_info.name = "wC0";
426 break;
427 case dwarf_wC1:
428 reg_info.name = "wC1";
429 break;
430 case dwarf_wC2:
431 reg_info.name = "wC2";
432 break;
433 case dwarf_wC3:
434 reg_info.name = "wC3";
435 break;
436 case dwarf_wC4:
437 reg_info.name = "wC4";
438 break;
439 case dwarf_wC5:
440 reg_info.name = "wC5";
441 break;
442 case dwarf_wC6:
443 reg_info.name = "wC6";
444 break;
445 case dwarf_wC7:
446 reg_info.name = "wC7";
447 break;
448
449 // VFP-v3/Neon
450 case dwarf_d0:
451 reg_info.name = "d0";
452 break;
453 case dwarf_d1:
454 reg_info.name = "d1";
455 break;
456 case dwarf_d2:
457 reg_info.name = "d2";
458 break;
459 case dwarf_d3:
460 reg_info.name = "d3";
461 break;
462 case dwarf_d4:
463 reg_info.name = "d4";
464 break;
465 case dwarf_d5:
466 reg_info.name = "d5";
467 break;
468 case dwarf_d6:
469 reg_info.name = "d6";
470 break;
471 case dwarf_d7:
472 reg_info.name = "d7";
473 break;
474 case dwarf_d8:
475 reg_info.name = "d8";
476 break;
477 case dwarf_d9:
478 reg_info.name = "d9";
479 break;
480 case dwarf_d10:
481 reg_info.name = "d10";
482 break;
483 case dwarf_d11:
484 reg_info.name = "d11";
485 break;
486 case dwarf_d12:
487 reg_info.name = "d12";
488 break;
489 case dwarf_d13:
490 reg_info.name = "d13";
491 break;
492 case dwarf_d14:
493 reg_info.name = "d14";
494 break;
495 case dwarf_d15:
496 reg_info.name = "d15";
497 break;
498 case dwarf_d16:
499 reg_info.name = "d16";
500 break;
501 case dwarf_d17:
502 reg_info.name = "d17";
503 break;
504 case dwarf_d18:
505 reg_info.name = "d18";
506 break;
507 case dwarf_d19:
508 reg_info.name = "d19";
509 break;
510 case dwarf_d20:
511 reg_info.name = "d20";
512 break;
513 case dwarf_d21:
514 reg_info.name = "d21";
515 break;
516 case dwarf_d22:
517 reg_info.name = "d22";
518 break;
519 case dwarf_d23:
520 reg_info.name = "d23";
521 break;
522 case dwarf_d24:
523 reg_info.name = "d24";
524 break;
525 case dwarf_d25:
526 reg_info.name = "d25";
527 break;
528 case dwarf_d26:
529 reg_info.name = "d26";
530 break;
531 case dwarf_d27:
532 reg_info.name = "d27";
533 break;
534 case dwarf_d28:
535 reg_info.name = "d28";
536 break;
537 case dwarf_d29:
538 reg_info.name = "d29";
539 break;
540 case dwarf_d30:
541 reg_info.name = "d30";
542 break;
543 case dwarf_d31:
544 reg_info.name = "d31";
545 break;
546
547 // NEON 128-bit vector registers (overlays the d registers)
548 case dwarf_q0:
549 reg_info.name = "q0";
550 break;
551 case dwarf_q1:
552 reg_info.name = "q1";
553 break;
554 case dwarf_q2:
555 reg_info.name = "q2";
556 break;
557 case dwarf_q3:
558 reg_info.name = "q3";
559 break;
560 case dwarf_q4:
561 reg_info.name = "q4";
562 break;
563 case dwarf_q5:
564 reg_info.name = "q5";
565 break;
566 case dwarf_q6:
567 reg_info.name = "q6";
568 break;
569 case dwarf_q7:
570 reg_info.name = "q7";
571 break;
572 case dwarf_q8:
573 reg_info.name = "q8";
574 break;
575 case dwarf_q9:
576 reg_info.name = "q9";
577 break;
578 case dwarf_q10:
579 reg_info.name = "q10";
580 break;
581 case dwarf_q11:
582 reg_info.name = "q11";
583 break;
584 case dwarf_q12:
585 reg_info.name = "q12";
586 break;
587 case dwarf_q13:
588 reg_info.name = "q13";
589 break;
590 case dwarf_q14:
591 reg_info.name = "q14";
592 break;
593 case dwarf_q15:
594 reg_info.name = "q15";
595 break;
596
597 default:
598 return {};
599 }
600 return reg_info;
601}
602
603// A8.6.50
604// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
605static uint32_t CountITSize(uint32_t ITMask) {
606 // First count the trailing zeros of the IT mask.
607 uint32_t TZ = llvm::countr_zero(ITMask);
608 if (TZ > 3) {
609 return 0;
610 }
611 return (4 - TZ);
612}
613
614// Init ITState. Note that at least one bit is always 1 in mask.
615bool ITSession::InitIT(uint32_t bits7_0) {
616 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
617 if (ITCounter == 0)
618 return false;
619
620 // A8.6.50 IT
621 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
622 if (FirstCond == 0xF) {
623 return false;
624 }
625 if (FirstCond == 0xE && ITCounter != 1) {
626 return false;
627 }
628
629 ITState = bits7_0;
630 return true;
631}
632
633// Update ITState if necessary.
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);
642 }
643}
644
645// Return true if we're inside an IT Block.
646bool ITSession::InITBlock() { return ITCounter != 0; }
647
648// Return true if we're the last instruction inside an IT Block.
649bool ITSession::LastInITBlock() { return ITCounter == 1; }
650
651// Get condition bits for the current thumb instruction.
653 if (InITBlock())
654 return Bits32(ITState, 7, 4);
655 else
656 return COND_AL;
657}
658
659// ARM constants used during decoding
660#define REG_RD 0
661#define LDM_REGLIST 1
662#define SP_REG 13
663#define LR_REG 14
664#define PC_REG 15
665#define PC_REGLIST_BIT 0x8000
666
667#define ARMv4 (1u << 0)
668#define ARMv4T (1u << 1)
669#define ARMv5T (1u << 2)
670#define ARMv5TE (1u << 3)
671#define ARMv5TEJ (1u << 4)
672#define ARMv6 (1u << 5)
673#define ARMv6K (1u << 6)
674#define ARMv6T2 (1u << 7)
675#define ARMv7 (1u << 8)
676#define ARMv7S (1u << 9)
677#define ARMv8 (1u << 10)
678#define ARMvAll (0xffffffffu)
679
680#define ARMV4T_ABOVE \
681 (ARMv4T | ARMv5T | ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | \
682 ARMv7S | ARMv8)
683#define ARMV5_ABOVE \
684 (ARMv5T | ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | \
685 ARMv8)
686#define ARMV5TE_ABOVE \
687 (ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
688#define ARMV5J_ABOVE \
689 (ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
690#define ARMV6_ABOVE (ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
691#define ARMV6T2_ABOVE (ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
692#define ARMV7_ABOVE (ARMv7 | ARMv7S | ARMv8)
693
694#define No_VFP 0
695#define VFPv1 (1u << 1)
696#define VFPv2 (1u << 2)
697#define VFPv3 (1u << 3)
698#define AdvancedSIMD (1u << 4)
699
700#define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD)
701#define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD)
702#define VFPv2v3 (VFPv2 | VFPv3)
703
704//
705// EmulateInstructionARM implementation
706//
707
711}
712
715}
716
718 return "Emulate instructions for the ARM architecture.";
719}
720
723 InstructionType inst_type) {
725 inst_type)) {
726 if (arch.GetTriple().getArch() == llvm::Triple::arm) {
727 std::unique_ptr<EmulateInstructionARM> emulate_insn_up(
728 new EmulateInstructionARM(arch));
729
730 if (emulate_insn_up)
731 return emulate_insn_up.release();
732 } else if (arch.GetTriple().getArch() == llvm::Triple::thumb) {
733 std::unique_ptr<EmulateInstructionARM> emulate_insn_up(
734 new EmulateInstructionARM(arch));
735
736 if (emulate_insn_up)
737 return emulate_insn_up.release();
738 }
739 }
740
741 return nullptr;
742}
743
745 if (arch.GetTriple().getArch() == llvm::Triple::arm)
746 return true;
747 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
748 return true;
749
750 return false;
751}
752
753// Write "bits (32) UNKNOWN" to memory address "address". Helper function for
754// many ARM instructions.
758 context.SetNoArgs();
759
760 uint32_t random_data = rand();
761 const uint32_t addr_byte_size = GetAddressByteSize();
762
763 return MemAWrite(context, address, random_data, addr_byte_size);
764}
765
766// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM
767// instructions.
771 context.SetNoArgs();
772
773 bool success;
774 uint32_t data =
776
777 if (!success)
778 return false;
779
780 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, data))
781 return false;
782
783 return true;
784}
785
786std::optional<RegisterInfo>
788 uint32_t reg_num) {
789 if (reg_kind == eRegisterKindGeneric) {
790 switch (reg_num) {
792 reg_kind = eRegisterKindDWARF;
793 reg_num = dwarf_pc;
794 break;
796 reg_kind = eRegisterKindDWARF;
797 reg_num = dwarf_sp;
798 break;
800 reg_kind = eRegisterKindDWARF;
801 reg_num = dwarf_r7;
802 break;
804 reg_kind = eRegisterKindDWARF;
805 reg_num = dwarf_lr;
806 break;
808 reg_kind = eRegisterKindDWARF;
809 reg_num = dwarf_cpsr;
810 break;
811 default:
812 return {};
813 }
814 }
815
816 if (reg_kind == eRegisterKindDWARF)
817 return GetARMDWARFRegisterInfo(reg_num);
818 return {};
819}
820
822 if (m_arch.GetTriple().isAndroid())
823 return LLDB_INVALID_REGNUM; // Don't use frame pointer on android
824 bool is_apple = false;
825 if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)
826 is_apple = true;
827 switch (m_arch.GetTriple().getOS()) {
828 case llvm::Triple::Darwin:
829 case llvm::Triple::MacOSX:
830 case llvm::Triple::IOS:
831 case llvm::Triple::TvOS:
832 case llvm::Triple::WatchOS:
833 case llvm::Triple::XROS:
834 case llvm::Triple::BridgeOS:
835 is_apple = true;
836 break;
837 default:
838 break;
839 }
840
841 /* On Apple iOS et al, the frame pointer register is always r7.
842 * Typically on other ARM systems, thumb code uses r7; arm code uses r11.
843 * Windows on ARM, which is in thumb mode, uses r11 though.
844 */
845
846 uint32_t fp_regnum = 11;
847
848 if (is_apple)
849 fp_regnum = 7;
850
851 if (m_opcode_mode == eModeThumb && !m_arch.GetTriple().isOSWindows())
852 fp_regnum = 7;
853
854 return fp_regnum;
855}
856
858 bool is_apple = false;
859 if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)
860 is_apple = true;
861 switch (m_arch.GetTriple().getOS()) {
862 case llvm::Triple::Darwin:
863 case llvm::Triple::MacOSX:
864 case llvm::Triple::IOS:
865 is_apple = true;
866 break;
867 default:
868 break;
869 }
870
871 /* On Apple iOS et al, the frame pointer register is always r7.
872 * Typically on other ARM systems, thumb code uses r7; arm code uses r11.
873 * Windows on ARM, which is in thumb mode, uses r11 though.
874 */
875
876 uint32_t fp_regnum = dwarf_r11;
877
878 if (is_apple)
879 fp_regnum = dwarf_r7;
880
881 if (m_opcode_mode == eModeThumb && !m_arch.GetTriple().isOSWindows())
882 fp_regnum = dwarf_r7;
883
884 return fp_regnum;
885}
886
887// Push Multiple Registers stores multiple registers to the stack, storing to
888// consecutive memory locations ending just below the address in SP, and
889// updates
890// SP to point to the start of the stored data.
891bool EmulateInstructionARM::EmulatePUSH(const uint32_t opcode,
892 const ARMEncoding encoding) {
893#if 0
894 // ARM pseudo code...
895 if (ConditionPassed())
896 {
897 EncodingSpecificOperations();
898 NullCheckIfThumbEE(13);
899 address = SP - 4*BitCount(registers);
900
901 for (i = 0 to 14)
902 {
903 if (registers<i> == '1')
904 {
905 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
906 MemA[address,4] = bits(32) UNKNOWN;
907 else
908 MemA[address,4] = R[i];
909 address = address + 4;
910 }
911 }
912
913 if (registers<15> == '1') // Only possible for encoding A1 or A2
914 MemA[address,4] = PCStoreValue();
915
916 SP = SP - 4*BitCount(registers);
917 }
918#endif
919
920 bool success = false;
921 if (ConditionPassed(opcode)) {
922 const uint32_t addr_byte_size = GetAddressByteSize();
923 const addr_t sp = ReadCoreReg(SP_REG, &success);
924 if (!success)
925 return false;
926 uint32_t registers = 0;
927 uint32_t Rt; // the source register
928 switch (encoding) {
929 case eEncodingT1:
930 registers = Bits32(opcode, 7, 0);
931 // The M bit represents LR.
932 if (Bit32(opcode, 8))
933 registers |= (1u << 14);
934 // if BitCount(registers) < 1 then UNPREDICTABLE;
935 if (BitCount(registers) < 1)
936 return false;
937 break;
938 case eEncodingT2:
939 // Ignore bits 15 & 13.
940 registers = Bits32(opcode, 15, 0) & ~0xa000;
941 // if BitCount(registers) < 2 then UNPREDICTABLE;
942 if (BitCount(registers) < 2)
943 return false;
944 break;
945 case eEncodingT3:
946 Rt = Bits32(opcode, 15, 12);
947 // if BadReg(t) then UNPREDICTABLE;
948 if (BadReg(Rt))
949 return false;
950 registers = (1u << Rt);
951 break;
952 case eEncodingA1:
953 registers = Bits32(opcode, 15, 0);
954 // Instead of return false, let's handle the following case as well,
955 // which amounts to pushing one reg onto the full descending stacks.
956 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
957 break;
958 case eEncodingA2:
959 Rt = Bits32(opcode, 15, 12);
960 // if t == 13 then UNPREDICTABLE;
961 if (Rt == dwarf_sp)
962 return false;
963 registers = (1u << Rt);
964 break;
965 default:
966 return false;
967 }
968 addr_t sp_offset = addr_byte_size * BitCount(registers);
969 addr_t addr = sp - sp_offset;
970 uint32_t i;
971
974 std::optional<RegisterInfo> sp_reg =
976 for (i = 0; i < 15; ++i) {
977 if (BitIsSet(registers, i)) {
978 std::optional<RegisterInfo> reg_info =
980 context.SetRegisterToRegisterPlusOffset(*reg_info, *sp_reg, addr - sp);
981 uint32_t reg_value = ReadCoreReg(i, &success);
982 if (!success)
983 return false;
984 if (!MemAWrite(context, addr, reg_value, addr_byte_size))
985 return false;
986 addr += addr_byte_size;
987 }
988 }
989
990 if (BitIsSet(registers, 15)) {
991 std::optional<RegisterInfo> reg_info =
993 context.SetRegisterToRegisterPlusOffset(*reg_info, *sp_reg, addr - sp);
994 const uint32_t pc = ReadCoreReg(PC_REG, &success);
995 if (!success)
996 return false;
997 if (!MemAWrite(context, addr, pc, addr_byte_size))
998 return false;
999 }
1000
1002 context.SetImmediateSigned(-sp_offset);
1003
1005 LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
1006 return false;
1007 }
1008 return true;
1009}
1010
1011// Pop Multiple Registers loads multiple registers from the stack, loading from
1012// consecutive memory locations staring at the address in SP, and updates
1013// SP to point just above the loaded data.
1014bool EmulateInstructionARM::EmulatePOP(const uint32_t opcode,
1015 const ARMEncoding encoding) {
1016#if 0
1017 // ARM pseudo code...
1018 if (ConditionPassed())
1019 {
1020 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
1021 address = SP;
1022 for i = 0 to 14
1023 if registers<i> == '1' then
1024 R[i] = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
1025 if registers<15> == '1' then
1026 if UnalignedAllowed then
1027 LoadWritePC(MemU[address,4]);
1028 else
1029 LoadWritePC(MemA[address,4]);
1030 if registers<13> == '0' then SP = SP + 4*BitCount(registers);
1031 if registers<13> == '1' then SP = bits(32) UNKNOWN;
1032 }
1033#endif
1034
1035 bool success = false;
1036
1037 if (ConditionPassed(opcode)) {
1038 const uint32_t addr_byte_size = GetAddressByteSize();
1039 const addr_t sp = ReadCoreReg(SP_REG, &success);
1040 if (!success)
1041 return false;
1042 uint32_t registers = 0;
1043 uint32_t Rt; // the destination register
1044 switch (encoding) {
1045 case eEncodingT1:
1046 registers = Bits32(opcode, 7, 0);
1047 // The P bit represents PC.
1048 if (Bit32(opcode, 8))
1049 registers |= (1u << 15);
1050 // if BitCount(registers) < 1 then UNPREDICTABLE;
1051 if (BitCount(registers) < 1)
1052 return false;
1053 break;
1054 case eEncodingT2:
1055 // Ignore bit 13.
1056 registers = Bits32(opcode, 15, 0) & ~0x2000;
1057 // if BitCount(registers) < 2 || (P == '1' && M == '1') then
1058 // UNPREDICTABLE;
1059 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
1060 return false;
1061 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
1062 // UNPREDICTABLE;
1063 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
1064 return false;
1065 break;
1066 case eEncodingT3:
1067 Rt = Bits32(opcode, 15, 12);
1068 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then
1069 // UNPREDICTABLE;
1070 if (Rt == 13)
1071 return false;
1072 if (Rt == 15 && InITBlock() && !LastInITBlock())
1073 return false;
1074 registers = (1u << Rt);
1075 break;
1076 case eEncodingA1:
1077 registers = Bits32(opcode, 15, 0);
1078 // Instead of return false, let's handle the following case as well,
1079 // which amounts to popping one reg from the full descending stacks.
1080 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
1081
1082 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
1083 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
1084 return false;
1085 break;
1086 case eEncodingA2:
1087 Rt = Bits32(opcode, 15, 12);
1088 // if t == 13 then UNPREDICTABLE;
1089 if (Rt == dwarf_sp)
1090 return false;
1091 registers = (1u << Rt);
1092 break;
1093 default:
1094 return false;
1095 }
1096 addr_t sp_offset = addr_byte_size * BitCount(registers);
1097 addr_t addr = sp;
1098 uint32_t i, data;
1099
1102
1103 std::optional<RegisterInfo> sp_reg =
1105
1106 for (i = 0; i < 15; ++i) {
1107 if (BitIsSet(registers, i)) {
1108 context.SetAddress(addr);
1109 data = MemARead(context, addr, 4, 0, &success);
1110 if (!success)
1111 return false;
1113 data))
1114 return false;
1115 addr += addr_byte_size;
1116 }
1117 }
1118
1119 if (BitIsSet(registers, 15)) {
1120 context.SetRegisterPlusOffset(*sp_reg, addr - sp);
1121 data = MemARead(context, addr, 4, 0, &success);
1122 if (!success)
1123 return false;
1124 // In ARMv5T and above, this is an interworking branch.
1125 if (!LoadWritePC(context, data))
1126 return false;
1127 // addr += addr_byte_size;
1128 }
1129
1131 context.SetImmediateSigned(sp_offset);
1132
1134 LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1135 return false;
1136 }
1137 return true;
1138}
1139
1140// Set r7 or ip to point to saved value residing within the stack.
1141// ADD (SP plus immediate)
1143 const ARMEncoding encoding) {
1144#if 0
1145 // ARM pseudo code...
1146 if (ConditionPassed())
1147 {
1148 EncodingSpecificOperations();
1149 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
1150 if d == 15 then
1151 ALUWritePC(result); // setflags is always FALSE here
1152 else
1153 R[d] = result;
1154 if setflags then
1155 APSR.N = result<31>;
1156 APSR.Z = IsZeroBit(result);
1157 APSR.C = carry;
1158 APSR.V = overflow;
1159 }
1160#endif
1161
1162 bool success = false;
1163
1164 if (ConditionPassed(opcode)) {
1165 const addr_t sp = ReadCoreReg(SP_REG, &success);
1166 if (!success)
1167 return false;
1168 uint32_t Rd; // the destination register
1169 uint32_t imm32;
1170 switch (encoding) {
1171 case eEncodingT1:
1172 Rd = 7;
1173 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
1174 break;
1175 case eEncodingA1:
1176 Rd = Bits32(opcode, 15, 12);
1177 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1178 break;
1179 default:
1180 return false;
1181 }
1182 addr_t sp_offset = imm32;
1183 addr_t addr = sp + sp_offset; // a pointer to the stack area
1184
1187 context.type = eContextSetFramePointer;
1188 else
1190 std::optional<RegisterInfo> sp_reg =
1192 context.SetRegisterPlusOffset(*sp_reg, sp_offset);
1193
1195 addr))
1196 return false;
1197 }
1198 return true;
1199}
1200
1201// Set r7 or ip to the current stack pointer.
1202// MOV (register)
1203bool EmulateInstructionARM::EmulateMOVRdSP(const uint32_t opcode,
1204 const ARMEncoding encoding) {
1205#if 0
1206 // ARM pseudo code...
1207 if (ConditionPassed())
1208 {
1209 EncodingSpecificOperations();
1210 result = R[m];
1211 if d == 15 then
1212 ALUWritePC(result); // setflags is always FALSE here
1213 else
1214 R[d] = result;
1215 if setflags then
1216 APSR.N = result<31>;
1217 APSR.Z = IsZeroBit(result);
1218 // APSR.C unchanged
1219 // APSR.V unchanged
1220 }
1221#endif
1222
1223 bool success = false;
1224
1225 if (ConditionPassed(opcode)) {
1226 const addr_t sp = ReadCoreReg(SP_REG, &success);
1227 if (!success)
1228 return false;
1229 uint32_t Rd; // the destination register
1230 switch (encoding) {
1231 case eEncodingT1:
1232 Rd = 7;
1233 break;
1234 case eEncodingA1:
1235 Rd = 12;
1236 break;
1237 default:
1238 return false;
1239 }
1240
1244 else
1246 std::optional<RegisterInfo> sp_reg =
1248 context.SetRegisterPlusOffset(*sp_reg, 0);
1249
1251 return false;
1252 }
1253 return true;
1254}
1255
1256// Move from high register (r8-r15) to low register (r0-r7).
1257// MOV (register)
1259 const ARMEncoding encoding) {
1260 return EmulateMOVRdRm(opcode, encoding);
1261}
1262
1263// Move from register to register.
1264// MOV (register)
1265bool EmulateInstructionARM::EmulateMOVRdRm(const uint32_t opcode,
1266 const ARMEncoding encoding) {
1267#if 0
1268 // ARM pseudo code...
1269 if (ConditionPassed())
1270 {
1271 EncodingSpecificOperations();
1272 result = R[m];
1273 if d == 15 then
1274 ALUWritePC(result); // setflags is always FALSE here
1275 else
1276 R[d] = result;
1277 if setflags then
1278 APSR.N = result<31>;
1279 APSR.Z = IsZeroBit(result);
1280 // APSR.C unchanged
1281 // APSR.V unchanged
1282 }
1283#endif
1284
1285 bool success = false;
1286
1287 if (ConditionPassed(opcode)) {
1288 uint32_t Rm; // the source register
1289 uint32_t Rd; // the destination register
1290 bool setflags;
1291 switch (encoding) {
1292 case eEncodingT1:
1293 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
1294 Rm = Bits32(opcode, 6, 3);
1295 setflags = false;
1296 if (Rd == 15 && InITBlock() && !LastInITBlock())
1297 return false;
1298 break;
1299 case eEncodingT2:
1300 Rd = Bits32(opcode, 2, 0);
1301 Rm = Bits32(opcode, 5, 3);
1302 setflags = true;
1303 if (InITBlock())
1304 return false;
1305 break;
1306 case eEncodingT3:
1307 Rd = Bits32(opcode, 11, 8);
1308 Rm = Bits32(opcode, 3, 0);
1309 setflags = BitIsSet(opcode, 20);
1310 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
1311 if (setflags && (BadReg(Rd) || BadReg(Rm)))
1312 return false;
1313 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then
1314 // UNPREDICTABLE;
1315 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
1316 return false;
1317 break;
1318 case eEncodingA1:
1319 Rd = Bits32(opcode, 15, 12);
1320 Rm = Bits32(opcode, 3, 0);
1321 setflags = BitIsSet(opcode, 20);
1322
1323 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1324 // instructions;
1325 if (Rd == 15 && setflags)
1326 return EmulateSUBSPcLrEtc(opcode, encoding);
1327 break;
1328 default:
1329 return false;
1330 }
1331 uint32_t result = ReadCoreReg(Rm, &success);
1332 if (!success)
1333 return false;
1334
1335 // The context specifies that Rm is to be moved into Rd.
1337 if (Rd == 13)
1339 else if (Rd == GetFramePointerRegisterNumber() && Rm == 13)
1341 else
1343 std::optional<RegisterInfo> dwarf_reg =
1345 context.SetRegisterPlusOffset(*dwarf_reg, 0);
1346
1347 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
1348 return false;
1349 }
1350 return true;
1351}
1352
1353// Move (immediate) writes an immediate value to the destination register. It
1354// can optionally update the condition flags based on the value.
1355// MOV (immediate)
1357 const ARMEncoding encoding) {
1358#if 0
1359 // ARM pseudo code...
1360 if (ConditionPassed())
1361 {
1362 EncodingSpecificOperations();
1363 result = imm32;
1364 if d == 15 then // Can only occur for ARM encoding
1365 ALUWritePC(result); // setflags is always FALSE here
1366 else
1367 R[d] = result;
1368 if setflags then
1369 APSR.N = result<31>;
1370 APSR.Z = IsZeroBit(result);
1371 APSR.C = carry;
1372 // APSR.V unchanged
1373 }
1374#endif
1375
1376 if (ConditionPassed(opcode)) {
1377 uint32_t Rd; // the destination register
1378 uint32_t imm32; // the immediate value to be written to Rd
1379 uint32_t carry =
1380 0; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
1381 // for setflags == false, this value is a don't care initialized to
1382 // 0 to silence the static analyzer
1383 bool setflags;
1384 switch (encoding) {
1385 case eEncodingT1:
1386 Rd = Bits32(opcode, 10, 8);
1387 setflags = !InITBlock();
1388 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
1389 carry = APSR_C;
1390
1391 break;
1392
1393 case eEncodingT2:
1394 Rd = Bits32(opcode, 11, 8);
1395 setflags = BitIsSet(opcode, 20);
1396 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
1397 if (BadReg(Rd))
1398 return false;
1399
1400 break;
1401
1402 case eEncodingT3: {
1403 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8,
1404 // 32);
1405 Rd = Bits32(opcode, 11, 8);
1406 setflags = false;
1407 uint32_t imm4 = Bits32(opcode, 19, 16);
1408 uint32_t imm3 = Bits32(opcode, 14, 12);
1409 uint32_t i = Bit32(opcode, 26);
1410 uint32_t imm8 = Bits32(opcode, 7, 0);
1411 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
1412
1413 // if BadReg(d) then UNPREDICTABLE;
1414 if (BadReg(Rd))
1415 return false;
1416 } break;
1417
1418 case eEncodingA1:
1419 // d = UInt(Rd); setflags = (S == '1'); (imm32, carry) =
1420 // ARMExpandImm_C(imm12, APSR.C);
1421 Rd = Bits32(opcode, 15, 12);
1422 setflags = BitIsSet(opcode, 20);
1423 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
1424
1425 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1426 // instructions;
1427 if ((Rd == 15) && setflags)
1428 return EmulateSUBSPcLrEtc(opcode, encoding);
1429
1430 break;
1431
1432 case eEncodingA2: {
1433 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
1434 Rd = Bits32(opcode, 15, 12);
1435 setflags = false;
1436 uint32_t imm4 = Bits32(opcode, 19, 16);
1437 uint32_t imm12 = Bits32(opcode, 11, 0);
1438 imm32 = (imm4 << 12) | imm12;
1439
1440 // if d == 15 then UNPREDICTABLE;
1441 if (Rd == 15)
1442 return false;
1443 } break;
1444
1445 default:
1446 return false;
1447 }
1448 uint32_t result = imm32;
1449
1450 // The context specifies that an immediate is to be moved into Rd.
1453 context.SetNoArgs();
1454
1455 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1456 return false;
1457 }
1458 return true;
1459}
1460
1461// MUL multiplies two register values. The least significant 32 bits of the
1462// result are written to the destination
1463// register. These 32 bits do not depend on whether the source register values
1464// are considered to be signed values or unsigned values.
1465//
1466// Optionally, it can update the condition flags based on the result. In the
1467// Thumb instruction set, this option is limited to only a few forms of the
1468// instruction.
1469bool EmulateInstructionARM::EmulateMUL(const uint32_t opcode,
1470 const ARMEncoding encoding) {
1471#if 0
1472 if ConditionPassed() then
1473 EncodingSpecificOperations();
1474 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
1475 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
1476 result = operand1 * operand2;
1477 R[d] = result<31:0>;
1478 if setflags then
1479 APSR.N = result<31>;
1480 APSR.Z = IsZeroBit(result);
1481 if ArchVersion() == 4 then
1482 APSR.C = bit UNKNOWN;
1483 // else APSR.C unchanged
1484 // APSR.V always unchanged
1485#endif
1486
1487 if (ConditionPassed(opcode)) {
1488 uint32_t d;
1489 uint32_t n;
1490 uint32_t m;
1491 bool setflags;
1492
1493 // EncodingSpecificOperations();
1494 switch (encoding) {
1495 case eEncodingT1:
1496 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
1497 d = Bits32(opcode, 2, 0);
1498 n = Bits32(opcode, 5, 3);
1499 m = Bits32(opcode, 2, 0);
1500 setflags = !InITBlock();
1501
1502 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
1503 if ((ArchVersion() < ARMv6) && (d == n))
1504 return false;
1505
1506 break;
1507
1508 case eEncodingT2:
1509 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
1510 d = Bits32(opcode, 11, 8);
1511 n = Bits32(opcode, 19, 16);
1512 m = Bits32(opcode, 3, 0);
1513 setflags = false;
1514
1515 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
1516 if (BadReg(d) || BadReg(n) || BadReg(m))
1517 return false;
1518
1519 break;
1520
1521 case eEncodingA1:
1522 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
1523 d = Bits32(opcode, 19, 16);
1524 n = Bits32(opcode, 3, 0);
1525 m = Bits32(opcode, 11, 8);
1526 setflags = BitIsSet(opcode, 20);
1527
1528 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
1529 if ((d == 15) || (n == 15) || (m == 15))
1530 return false;
1531
1532 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
1533 if ((ArchVersion() < ARMv6) && (d == n))
1534 return false;
1535
1536 break;
1537
1538 default:
1539 return false;
1540 }
1541
1542 bool success = false;
1543
1544 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final
1545 // results
1546 uint64_t operand1 =
1548 if (!success)
1549 return false;
1550
1551 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final
1552 // results
1553 uint64_t operand2 =
1555 if (!success)
1556 return false;
1557
1558 // result = operand1 * operand2;
1559 uint64_t result = operand1 * operand2;
1560
1561 // R[d] = result<31:0>;
1562 std::optional<RegisterInfo> op1_reg =
1564 std::optional<RegisterInfo> op2_reg =
1566
1568 context.type = eContextArithmetic;
1569 context.SetRegisterRegisterOperands(*op1_reg, *op2_reg);
1570
1572 (0x0000ffff & result)))
1573 return false;
1574
1575 // if setflags then
1576 if (setflags) {
1577 // APSR.N = result<31>;
1578 // APSR.Z = IsZeroBit(result);
1581 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
1585 return false;
1586 }
1587
1588 // if ArchVersion() == 4 then
1589 // APSR.C = bit UNKNOWN;
1590 }
1591 }
1592 return true;
1593}
1594
1595// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to
1596// the destination register. It can optionally update the condition flags based
1597// on the value.
1598bool EmulateInstructionARM::EmulateMVNImm(const uint32_t opcode,
1599 const ARMEncoding encoding) {
1600#if 0
1601 // ARM pseudo code...
1602 if (ConditionPassed())
1603 {
1604 EncodingSpecificOperations();
1605 result = NOT(imm32);
1606 if d == 15 then // Can only occur for ARM encoding
1607 ALUWritePC(result); // setflags is always FALSE here
1608 else
1609 R[d] = result;
1610 if setflags then
1611 APSR.N = result<31>;
1612 APSR.Z = IsZeroBit(result);
1613 APSR.C = carry;
1614 // APSR.V unchanged
1615 }
1616#endif
1617
1618 if (ConditionPassed(opcode)) {
1619 uint32_t Rd; // the destination register
1620 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
1621 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
1622 bool setflags;
1623 switch (encoding) {
1624 case eEncodingT1:
1625 Rd = Bits32(opcode, 11, 8);
1626 setflags = BitIsSet(opcode, 20);
1627 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
1628 break;
1629 case eEncodingA1:
1630 Rd = Bits32(opcode, 15, 12);
1631 setflags = BitIsSet(opcode, 20);
1632 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
1633
1634 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1635 // instructions;
1636 if (Rd == 15 && setflags)
1637 return EmulateSUBSPcLrEtc(opcode, encoding);
1638 break;
1639 default:
1640 return false;
1641 }
1642 uint32_t result = ~imm32;
1643
1644 // The context specifies that an immediate is to be moved into Rd.
1647 context.SetNoArgs();
1648
1649 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1650 return false;
1651 }
1652 return true;
1653}
1654
1655// Bitwise NOT (register) writes the bitwise inverse of a register value to the
1656// destination register. It can optionally update the condition flags based on
1657// the result.
1658bool EmulateInstructionARM::EmulateMVNReg(const uint32_t opcode,
1659 const ARMEncoding encoding) {
1660#if 0
1661 // ARM pseudo code...
1662 if (ConditionPassed())
1663 {
1664 EncodingSpecificOperations();
1665 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
1666 result = NOT(shifted);
1667 if d == 15 then // Can only occur for ARM encoding
1668 ALUWritePC(result); // setflags is always FALSE here
1669 else
1670 R[d] = result;
1671 if setflags then
1672 APSR.N = result<31>;
1673 APSR.Z = IsZeroBit(result);
1674 APSR.C = carry;
1675 // APSR.V unchanged
1676 }
1677#endif
1678
1679 if (ConditionPassed(opcode)) {
1680 uint32_t Rm; // the source register
1681 uint32_t Rd; // the destination register
1682 ARM_ShifterType shift_t;
1683 uint32_t shift_n; // the shift applied to the value read from Rm
1684 bool setflags;
1685 uint32_t carry; // the carry bit after the shift operation
1686 switch (encoding) {
1687 case eEncodingT1:
1688 Rd = Bits32(opcode, 2, 0);
1689 Rm = Bits32(opcode, 5, 3);
1690 setflags = !InITBlock();
1691 shift_t = SRType_LSL;
1692 shift_n = 0;
1693 if (InITBlock())
1694 return false;
1695 break;
1696 case eEncodingT2:
1697 Rd = Bits32(opcode, 11, 8);
1698 Rm = Bits32(opcode, 3, 0);
1699 setflags = BitIsSet(opcode, 20);
1700 shift_n = DecodeImmShiftThumb(opcode, shift_t);
1701 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
1702 if (BadReg(Rd) || BadReg(Rm))
1703 return false;
1704 break;
1705 case eEncodingA1:
1706 Rd = Bits32(opcode, 15, 12);
1707 Rm = Bits32(opcode, 3, 0);
1708 setflags = BitIsSet(opcode, 20);
1709 shift_n = DecodeImmShiftARM(opcode, shift_t);
1710 break;
1711 default:
1712 return false;
1713 }
1714 bool success = false;
1715 uint32_t value = ReadCoreReg(Rm, &success);
1716 if (!success)
1717 return false;
1718
1719 uint32_t shifted =
1720 Shift_C(value, shift_t, shift_n, APSR_C, carry, &success);
1721 if (!success)
1722 return false;
1723 uint32_t result = ~shifted;
1724
1725 // The context specifies that an immediate is to be moved into Rd.
1728 context.SetNoArgs();
1729
1730 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1731 return false;
1732 }
1733 return true;
1734}
1735
1736// PC relative immediate load into register, possibly followed by ADD (SP plus
1737// register).
1738// LDR (literal)
1740 const ARMEncoding encoding) {
1741#if 0
1742 // ARM pseudo code...
1743 if (ConditionPassed())
1744 {
1745 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1746 base = Align(PC,4);
1747 address = if add then (base + imm32) else (base - imm32);
1748 data = MemU[address,4];
1749 if t == 15 then
1750 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1751 elsif UnalignedSupport() || address<1:0> = '00' then
1752 R[t] = data;
1753 else // Can only apply before ARMv7
1754 if CurrentInstrSet() == InstrSet_ARM then
1755 R[t] = ROR(data, 8*UInt(address<1:0>));
1756 else
1757 R[t] = bits(32) UNKNOWN;
1758 }
1759#endif
1760
1761 if (ConditionPassed(opcode)) {
1762 bool success = false;
1763 const uint32_t pc = ReadCoreReg(PC_REG, &success);
1764 if (!success)
1765 return false;
1766
1767 // PC relative immediate load context
1770 std::optional<RegisterInfo> pc_reg =
1772 context.SetRegisterPlusOffset(*pc_reg, 0);
1773
1774 uint32_t Rt; // the destination register
1775 uint32_t imm32; // immediate offset from the PC
1776 bool add; // +imm32 or -imm32?
1777 addr_t base; // the base address
1778 addr_t address; // the PC relative address
1779 uint32_t data; // the literal data value from the PC relative load
1780 switch (encoding) {
1781 case eEncodingT1:
1782 Rt = Bits32(opcode, 10, 8);
1783 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
1784 add = true;
1785 break;
1786 case eEncodingT2:
1787 Rt = Bits32(opcode, 15, 12);
1788 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1789 add = BitIsSet(opcode, 23);
1790 if (Rt == 15 && InITBlock() && !LastInITBlock())
1791 return false;
1792 break;
1793 default:
1794 return false;
1795 }
1796
1797 base = Align(pc, 4);
1798 if (add)
1799 address = base + imm32;
1800 else
1801 address = base - imm32;
1802
1803 context.SetRegisterPlusOffset(*pc_reg, address - base);
1804 data = MemURead(context, address, 4, 0, &success);
1805 if (!success)
1806 return false;
1807
1808 if (Rt == 15) {
1809 if (Bits32(address, 1, 0) == 0) {
1810 // In ARMv5T and above, this is an interworking branch.
1811 if (!LoadWritePC(context, data))
1812 return false;
1813 } else
1814 return false;
1815 } else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) {
1817 data))
1818 return false;
1819 } else // We don't handle ARM for now.
1820 return false;
1821 }
1822 return true;
1823}
1824
1825// An add operation to adjust the SP.
1826// ADD (SP plus immediate)
1828 const ARMEncoding encoding) {
1829#if 0
1830 // ARM pseudo code...
1831 if (ConditionPassed())
1832 {
1833 EncodingSpecificOperations();
1834 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
1835 if d == 15 then // Can only occur for ARM encoding
1836 ALUWritePC(result); // setflags is always FALSE here
1837 else
1838 R[d] = result;
1839 if setflags then
1840 APSR.N = result<31>;
1841 APSR.Z = IsZeroBit(result);
1842 APSR.C = carry;
1843 APSR.V = overflow;
1844 }
1845#endif
1846
1847 bool success = false;
1848
1849 if (ConditionPassed(opcode)) {
1850 const addr_t sp = ReadCoreReg(SP_REG, &success);
1851 if (!success)
1852 return false;
1853 uint32_t imm32; // the immediate operand
1854 uint32_t d;
1855 bool setflags;
1856 switch (encoding) {
1857 case eEncodingT1:
1858 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
1859 d = Bits32(opcode, 10, 8);
1860 imm32 = (Bits32(opcode, 7, 0) << 2);
1861 setflags = false;
1862 break;
1863
1864 case eEncodingT2:
1865 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
1866 d = 13;
1867 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1868 setflags = false;
1869 break;
1870
1871 case eEncodingT3:
1872 // d = UInt(Rd); setflags = (S == "1"); imm32 =
1873 // ThumbExpandImm(i:imm3:imm8);
1874 d = Bits32(opcode, 11, 8);
1875 imm32 = ThumbExpandImm(opcode);
1876 setflags = Bit32(opcode, 20);
1877
1878 // if Rd == "1111" && S == "1" then SEE CMN (immediate);
1879 if (d == 15 && setflags == 1)
1880 return false; // CMN (immediate) not yet supported
1881
1882 // if d == 15 && S == "0" then UNPREDICTABLE;
1883 if (d == 15 && setflags == 0)
1884 return false;
1885 break;
1886
1887 case eEncodingT4: {
1888 // if Rn == '1111' then SEE ADR;
1889 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
1890 d = Bits32(opcode, 11, 8);
1891 setflags = false;
1892 uint32_t i = Bit32(opcode, 26);
1893 uint32_t imm3 = Bits32(opcode, 14, 12);
1894 uint32_t imm8 = Bits32(opcode, 7, 0);
1895 imm32 = (i << 11) | (imm3 << 8) | imm8;
1896
1897 // if d == 15 then UNPREDICTABLE;
1898 if (d == 15)
1899 return false;
1900 } break;
1901
1902 default:
1903 return false;
1904 }
1905 // (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
1906 AddWithCarryResult res = AddWithCarry(sp, imm32, 0);
1907
1909 if (d == 13)
1911 else
1913
1914 std::optional<RegisterInfo> sp_reg =
1916 context.SetRegisterPlusOffset(*sp_reg, res.result - sp);
1917
1918 if (d == 15) {
1919 if (!ALUWritePC(context, res.result))
1920 return false;
1921 } else {
1922 // R[d] = result;
1923 // if setflags then
1924 // APSR.N = result<31>;
1925 // APSR.Z = IsZeroBit(result);
1926 // APSR.C = carry;
1927 // APSR.V = overflow;
1928 if (!WriteCoreRegOptionalFlags(context, res.result, d, setflags,
1929 res.carry_out, res.overflow))
1930 return false;
1931 }
1932 }
1933 return true;
1934}
1935
1936// An add operation to adjust the SP.
1937// ADD (SP plus register)
1938bool EmulateInstructionARM::EmulateADDSPRm(const uint32_t opcode,
1939 const ARMEncoding encoding) {
1940#if 0
1941 // ARM pseudo code...
1942 if (ConditionPassed())
1943 {
1944 EncodingSpecificOperations();
1945 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1946 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
1947 if d == 15 then
1948 ALUWritePC(result); // setflags is always FALSE here
1949 else
1950 R[d] = result;
1951 if setflags then
1952 APSR.N = result<31>;
1953 APSR.Z = IsZeroBit(result);
1954 APSR.C = carry;
1955 APSR.V = overflow;
1956 }
1957#endif
1958
1959 bool success = false;
1960
1961 if (ConditionPassed(opcode)) {
1962 const addr_t sp = ReadCoreReg(SP_REG, &success);
1963 if (!success)
1964 return false;
1965 uint32_t Rm; // the second operand
1966 switch (encoding) {
1967 case eEncodingT2:
1968 Rm = Bits32(opcode, 6, 3);
1969 break;
1970 default:
1971 return false;
1972 }
1973 int32_t reg_value = ReadCoreReg(Rm, &success);
1974 if (!success)
1975 return false;
1976
1977 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1978
1980 context.type = eContextArithmetic;
1981 std::optional<RegisterInfo> sp_reg =
1983 std::optional<RegisterInfo> other_reg =
1985 context.SetRegisterRegisterOperands(*sp_reg, *other_reg);
1986
1989 return false;
1990 }
1991 return true;
1992}
1993
1994// Branch with Link and Exchange Instruction Sets (immediate) calls a
1995// subroutine at a PC-relative address, and changes instruction set from ARM to
1996// Thumb, or from Thumb to ARM.
1997// BLX (immediate)
1999 const ARMEncoding encoding) {
2000#if 0
2001 // ARM pseudo code...
2002 if (ConditionPassed())
2003 {
2004 EncodingSpecificOperations();
2005 if CurrentInstrSet() == InstrSet_ARM then
2006 LR = PC - 4;
2007 else
2008 LR = PC<31:1> : '1';
2009 if targetInstrSet == InstrSet_ARM then
2010 targetAddress = Align(PC,4) + imm32;
2011 else
2012 targetAddress = PC + imm32;
2013 SelectInstrSet(targetInstrSet);
2014 BranchWritePC(targetAddress);
2015 }
2016#endif
2017
2018 bool success = true;
2019
2020 if (ConditionPassed(opcode)) {
2023 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2024 if (!success)
2025 return false;
2026 addr_t lr; // next instruction address
2027 addr_t target; // target address
2028 int32_t imm32; // PC-relative offset
2029 switch (encoding) {
2030 case eEncodingT1: {
2031 lr = pc | 1u; // return address
2032 uint32_t S = Bit32(opcode, 26);
2033 uint32_t imm10 = Bits32(opcode, 25, 16);
2034 uint32_t J1 = Bit32(opcode, 13);
2035 uint32_t J2 = Bit32(opcode, 11);
2036 uint32_t imm11 = Bits32(opcode, 10, 0);
2037 uint32_t I1 = !(J1 ^ S);
2038 uint32_t I2 = !(J2 ^ S);
2039 uint32_t imm25 =
2040 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
2041 imm32 = llvm::SignExtend32<25>(imm25);
2042 target = pc + imm32;
2044 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2045 if (InITBlock() && !LastInITBlock())
2046 return false;
2047 break;
2048 }
2049 case eEncodingT2: {
2050 lr = pc | 1u; // return address
2051 uint32_t S = Bit32(opcode, 26);
2052 uint32_t imm10H = Bits32(opcode, 25, 16);
2053 uint32_t J1 = Bit32(opcode, 13);
2054 uint32_t J2 = Bit32(opcode, 11);
2055 uint32_t imm10L = Bits32(opcode, 10, 1);
2056 uint32_t I1 = !(J1 ^ S);
2057 uint32_t I2 = !(J2 ^ S);
2058 uint32_t imm25 =
2059 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
2060 imm32 = llvm::SignExtend32<25>(imm25);
2061 target = Align(pc, 4) + imm32;
2063 context.SetISAAndImmediateSigned(eModeARM, 4 + imm32);
2064 if (InITBlock() && !LastInITBlock())
2065 return false;
2066 break;
2067 }
2068 case eEncodingA1:
2069 lr = pc - 4; // return address
2070 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
2071 target = Align(pc, 4) + imm32;
2073 context.SetISAAndImmediateSigned(eModeARM, 8 + imm32);
2074 break;
2075 case eEncodingA2:
2076 lr = pc - 4; // return address
2077 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 |
2078 Bits32(opcode, 24, 24) << 1);
2079 target = pc + imm32;
2081 context.SetISAAndImmediateSigned(eModeThumb, 8 + imm32);
2082 break;
2083 default:
2084 return false;
2085 }
2088 return false;
2089 if (!BranchWritePC(context, target))
2090 return false;
2094 return false;
2095 }
2096 return true;
2097}
2098
2099// Branch with Link and Exchange (register) calls a subroutine at an address
2100// and instruction set specified by a register.
2101// BLX (register)
2102bool EmulateInstructionARM::EmulateBLXRm(const uint32_t opcode,
2103 const ARMEncoding encoding) {
2104#if 0
2105 // ARM pseudo code...
2106 if (ConditionPassed())
2107 {
2108 EncodingSpecificOperations();
2109 target = R[m];
2110 if CurrentInstrSet() == InstrSet_ARM then
2111 next_instr_addr = PC - 4;
2112 LR = next_instr_addr;
2113 else
2114 next_instr_addr = PC - 2;
2115 LR = next_instr_addr<31:1> : '1';
2116 BXWritePC(target);
2117 }
2118#endif
2119
2120 bool success = false;
2121
2122 if (ConditionPassed(opcode)) {
2125 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2126 addr_t lr; // next instruction address
2127 if (!success)
2128 return false;
2129 uint32_t Rm; // the register with the target address
2130 switch (encoding) {
2131 case eEncodingT1:
2132 lr = (pc - 2) | 1u; // return address
2133 Rm = Bits32(opcode, 6, 3);
2134 // if m == 15 then UNPREDICTABLE;
2135 if (Rm == 15)
2136 return false;
2137 if (InITBlock() && !LastInITBlock())
2138 return false;
2139 break;
2140 case eEncodingA1:
2141 lr = pc - 4; // return address
2142 Rm = Bits32(opcode, 3, 0);
2143 // if m == 15 then UNPREDICTABLE;
2144 if (Rm == 15)
2145 return false;
2146 break;
2147 default:
2148 return false;
2149 }
2150 addr_t target = ReadCoreReg(Rm, &success);
2151 if (!success)
2152 return false;
2153 std::optional<RegisterInfo> dwarf_reg =
2155 context.SetRegister(*dwarf_reg);
2158 return false;
2159 if (!BXWritePC(context, target))
2160 return false;
2161 }
2162 return true;
2163}
2164
2165// Branch and Exchange causes a branch to an address and instruction set
2166// specified by a register.
2167bool EmulateInstructionARM::EmulateBXRm(const uint32_t opcode,
2168 const ARMEncoding encoding) {
2169#if 0
2170 // ARM pseudo code...
2171 if (ConditionPassed())
2172 {
2173 EncodingSpecificOperations();
2174 BXWritePC(R[m]);
2175 }
2176#endif
2177
2178 if (ConditionPassed(opcode)) {
2181 uint32_t Rm; // the register with the target address
2182 switch (encoding) {
2183 case eEncodingT1:
2184 Rm = Bits32(opcode, 6, 3);
2185 if (InITBlock() && !LastInITBlock())
2186 return false;
2187 break;
2188 case eEncodingA1:
2189 Rm = Bits32(opcode, 3, 0);
2190 break;
2191 default:
2192 return false;
2193 }
2194 bool success = false;
2195 addr_t target = ReadCoreReg(Rm, &success);
2196 if (!success)
2197 return false;
2198
2199 std::optional<RegisterInfo> dwarf_reg =
2201 context.SetRegister(*dwarf_reg);
2202 if (!BXWritePC(context, target))
2203 return false;
2204 }
2205 return true;
2206}
2207
2208// Branch and Exchange Jazelle attempts to change to Jazelle state. If the
2209// attempt fails, it branches to an address and instruction set specified by a
2210// register as though it were a BX instruction.
2211//
2212// TODO: Emulate Jazelle architecture?
2213// We currently assume that switching to Jazelle state fails, thus
2214// treating BXJ as a BX operation.
2215bool EmulateInstructionARM::EmulateBXJRm(const uint32_t opcode,
2216 const ARMEncoding encoding) {
2217#if 0
2218 // ARM pseudo code...
2219 if (ConditionPassed())
2220 {
2221 EncodingSpecificOperations();
2222 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
2223 BXWritePC(R[m]);
2224 else
2225 if JazelleAcceptsExecution() then
2226 SwitchToJazelleExecution();
2227 else
2228 SUBARCHITECTURE_DEFINED handler call;
2229 }
2230#endif
2231
2232 if (ConditionPassed(opcode)) {
2235 uint32_t Rm; // the register with the target address
2236 switch (encoding) {
2237 case eEncodingT1:
2238 Rm = Bits32(opcode, 19, 16);
2239 if (BadReg(Rm))
2240 return false;
2241 if (InITBlock() && !LastInITBlock())
2242 return false;
2243 break;
2244 case eEncodingA1:
2245 Rm = Bits32(opcode, 3, 0);
2246 if (Rm == 15)
2247 return false;
2248 break;
2249 default:
2250 return false;
2251 }
2252 bool success = false;
2253 addr_t target = ReadCoreReg(Rm, &success);
2254 if (!success)
2255 return false;
2256
2257 std::optional<RegisterInfo> dwarf_reg =
2259 context.SetRegister(*dwarf_reg);
2260 if (!BXWritePC(context, target))
2261 return false;
2262 }
2263 return true;
2264}
2265
2266// Set r7 to point to some ip offset.
2267// SUB (immediate)
2269 const ARMEncoding encoding) {
2270#if 0
2271 // ARM pseudo code...
2272 if (ConditionPassed())
2273 {
2274 EncodingSpecificOperations();
2275 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
2276 if d == 15 then // Can only occur for ARM encoding
2277 ALUWritePC(result); // setflags is always FALSE here
2278 else
2279 R[d] = result;
2280 if setflags then
2281 APSR.N = result<31>;
2282 APSR.Z = IsZeroBit(result);
2283 APSR.C = carry;
2284 APSR.V = overflow;
2285 }
2286#endif
2287
2288 if (ConditionPassed(opcode)) {
2289 bool success = false;
2290 const addr_t ip = ReadCoreReg(12, &success);
2291 if (!success)
2292 return false;
2293 uint32_t imm32;
2294 switch (encoding) {
2295 case eEncodingA1:
2296 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2297 break;
2298 default:
2299 return false;
2300 }
2301 addr_t ip_offset = imm32;
2302 addr_t addr = ip - ip_offset; // the adjusted ip value
2303
2306 std::optional<RegisterInfo> dwarf_reg =
2308 context.SetRegisterPlusOffset(*dwarf_reg, -ip_offset);
2309
2311 return false;
2312 }
2313 return true;
2314}
2315
2316// Set ip to point to some stack offset.
2317// SUB (SP minus immediate)
2319 const ARMEncoding encoding) {
2320#if 0
2321 // ARM pseudo code...
2322 if (ConditionPassed())
2323 {
2324 EncodingSpecificOperations();
2325 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
2326 if d == 15 then // Can only occur for ARM encoding
2327 ALUWritePC(result); // setflags is always FALSE here
2328 else
2329 R[d] = result;
2330 if setflags then
2331 APSR.N = result<31>;
2332 APSR.Z = IsZeroBit(result);
2333 APSR.C = carry;
2334 APSR.V = overflow;
2335 }
2336#endif
2337
2338 if (ConditionPassed(opcode)) {
2339 bool success = false;
2340 const addr_t sp = ReadCoreReg(SP_REG, &success);
2341 if (!success)
2342 return false;
2343 uint32_t imm32;
2344 switch (encoding) {
2345 case eEncodingA1:
2346 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2347 break;
2348 default:
2349 return false;
2350 }
2351 addr_t sp_offset = imm32;
2352 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
2353
2356 std::optional<RegisterInfo> dwarf_reg =
2358 context.SetRegisterPlusOffset(*dwarf_reg, -sp_offset);
2359
2361 return false;
2362 }
2363 return true;
2364}
2365
2366// This instruction subtracts an immediate value from the SP value, and writes
2367// the result to the destination register.
2368//
2369// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local
2370// storage.
2372 const ARMEncoding encoding) {
2373#if 0
2374 // ARM pseudo code...
2375 if (ConditionPassed())
2376 {
2377 EncodingSpecificOperations();
2378 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
2379 if d == 15 then // Can only occur for ARM encoding
2380 ALUWritePC(result); // setflags is always FALSE here
2381 else
2382 R[d] = result;
2383 if setflags then
2384 APSR.N = result<31>;
2385 APSR.Z = IsZeroBit(result);
2386 APSR.C = carry;
2387 APSR.V = overflow;
2388 }
2389#endif
2390
2391 bool success = false;
2392 if (ConditionPassed(opcode)) {
2393 const addr_t sp = ReadCoreReg(SP_REG, &success);
2394 if (!success)
2395 return false;
2396
2397 uint32_t Rd;
2398 bool setflags;
2399 uint32_t imm32;
2400 switch (encoding) {
2401 case eEncodingT1:
2402 Rd = 13;
2403 setflags = false;
2404 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
2405 break;
2406 case eEncodingT2:
2407 Rd = Bits32(opcode, 11, 8);
2408 setflags = BitIsSet(opcode, 20);
2409 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2410 if (Rd == 15 && setflags)
2411 return EmulateCMPImm(opcode, eEncodingT2);
2412 if (Rd == 15 && !setflags)
2413 return false;
2414 break;
2415 case eEncodingT3:
2416 Rd = Bits32(opcode, 11, 8);
2417 setflags = false;
2418 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
2419 if (Rd == 15)
2420 return false;
2421 break;
2422 case eEncodingA1:
2423 Rd = Bits32(opcode, 15, 12);
2424 setflags = BitIsSet(opcode, 20);
2425 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2426
2427 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
2428 // instructions;
2429 if (Rd == 15 && setflags)
2430 return EmulateSUBSPcLrEtc(opcode, encoding);
2431 break;
2432 default:
2433 return false;
2434 }
2435 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
2436
2438 if (Rd == 13) {
2439 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting
2440 // to negate it, or the wrong
2441 // value gets passed down to context.SetImmediateSigned.
2443 context.SetImmediateSigned(-imm64); // the stack pointer offset
2444 } else {
2446 context.SetNoArgs();
2447 }
2448
2449 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
2450 res.carry_out, res.overflow))
2451 return false;
2452 }
2453 return true;
2454}
2455
2456// A store operation to the stack that also updates the SP.
2457bool EmulateInstructionARM::EmulateSTRRtSP(const uint32_t opcode,
2458 const ARMEncoding encoding) {
2459#if 0
2460 // ARM pseudo code...
2461 if (ConditionPassed())
2462 {
2463 EncodingSpecificOperations();
2464 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
2465 address = if index then offset_addr else R[n];
2466 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
2467 if wback then R[n] = offset_addr;
2468 }
2469#endif
2470
2471 bool success = false;
2472 if (ConditionPassed(opcode)) {
2473 const uint32_t addr_byte_size = GetAddressByteSize();
2474 const addr_t sp = ReadCoreReg(SP_REG, &success);
2475 if (!success)
2476 return false;
2477 uint32_t Rt; // the source register
2478 uint32_t imm12;
2479 uint32_t
2480 Rn; // This function assumes Rn is the SP, but we should verify that.
2481
2482 bool index;
2483 bool add;
2484 bool wback;
2485 switch (encoding) {
2486 case eEncodingA1:
2487 Rt = Bits32(opcode, 15, 12);
2488 imm12 = Bits32(opcode, 11, 0);
2489 Rn = Bits32(opcode, 19, 16);
2490
2491 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
2492 return false;
2493
2494 index = BitIsSet(opcode, 24);
2495 add = BitIsSet(opcode, 23);
2496 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
2497
2498 if (wback && ((Rn == 15) || (Rn == Rt)))
2499 return false;
2500 break;
2501 default:
2502 return false;
2503 }
2504 addr_t offset_addr;
2505 if (add)
2506 offset_addr = sp + imm12;
2507 else
2508 offset_addr = sp - imm12;
2509
2510 addr_t addr;
2511 if (index)
2512 addr = offset_addr;
2513 else
2514 addr = sp;
2515
2518 std::optional<RegisterInfo> sp_reg =
2520 std::optional<RegisterInfo> dwarf_reg =
2522
2523 context.SetRegisterToRegisterPlusOffset(*dwarf_reg, *sp_reg, addr - sp);
2524 if (Rt != 15) {
2525 uint32_t reg_value = ReadCoreReg(Rt, &success);
2526 if (!success)
2527 return false;
2528 if (!MemUWrite(context, addr, reg_value, addr_byte_size))
2529 return false;
2530 } else {
2531 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2532 if (!success)
2533 return false;
2534 if (!MemUWrite(context, addr, pc, addr_byte_size))
2535 return false;
2536 }
2537
2538 if (wback) {
2540 context.SetImmediateSigned(addr - sp);
2542 LLDB_REGNUM_GENERIC_SP, offset_addr))
2543 return false;
2544 }
2545 }
2546 return true;
2547}
2548
2549// Vector Push stores multiple extension registers to the stack. It also
2550// updates SP to point to the start of the stored data.
2551bool EmulateInstructionARM::EmulateVPUSH(const uint32_t opcode,
2552 const ARMEncoding encoding) {
2553#if 0
2554 // ARM pseudo code...
2555 if (ConditionPassed())
2556 {
2557 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2558 address = SP - imm32;
2559 SP = SP - imm32;
2560 if single_regs then
2561 for r = 0 to regs-1
2562 MemA[address,4] = S[d+r]; address = address+4;
2563 else
2564 for r = 0 to regs-1
2565 // Store as two word-aligned words in the correct order for
2566 // current endianness.
2567 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
2568 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
2569 address = address+8;
2570 }
2571#endif
2572
2573 bool success = false;
2574 if (ConditionPassed(opcode)) {
2575 const uint32_t addr_byte_size = GetAddressByteSize();
2576 const addr_t sp = ReadCoreReg(SP_REG, &success);
2577 if (!success)
2578 return false;
2579 bool single_regs;
2580 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2581 uint32_t imm32; // stack offset
2582 uint32_t regs; // number of registers
2583 switch (encoding) {
2584 case eEncodingT1:
2585 case eEncodingA1:
2586 single_regs = false;
2587 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
2588 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2589 // If UInt(imm8) is odd, see "FSTMX".
2590 regs = Bits32(opcode, 7, 0) / 2;
2591 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2592 if (regs == 0 || regs > 16 || (d + regs) > 32)
2593 return false;
2594 break;
2595 case eEncodingT2:
2596 case eEncodingA2:
2597 single_regs = true;
2598 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
2599 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2600 regs = Bits32(opcode, 7, 0);
2601 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2602 if (regs == 0 || regs > 16 || (d + regs) > 32)
2603 return false;
2604 break;
2605 default:
2606 return false;
2607 }
2608 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2609 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2610 addr_t sp_offset = imm32;
2611 addr_t addr = sp - sp_offset;
2612 uint32_t i;
2613
2616
2617 std::optional<RegisterInfo> sp_reg =
2619 for (i = 0; i < regs; ++i) {
2620 std::optional<RegisterInfo> dwarf_reg =
2621 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i);
2622 context.SetRegisterToRegisterPlusOffset(*dwarf_reg, *sp_reg, addr - sp);
2623 // uint64_t to accommodate 64-bit registers.
2624 uint64_t reg_value = ReadRegisterUnsigned(*dwarf_reg, 0, &success);
2625 if (!success)
2626 return false;
2627 if (!MemAWrite(context, addr, reg_value, reg_byte_size))
2628 return false;
2629 addr += reg_byte_size;
2630 }
2631
2633 context.SetImmediateSigned(-sp_offset);
2634
2636 LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
2637 return false;
2638 }
2639 return true;
2640}
2641
2642// Vector Pop loads multiple extension registers from the stack. It also
2643// updates SP to point just above the loaded data.
2644bool EmulateInstructionARM::EmulateVPOP(const uint32_t opcode,
2645 const ARMEncoding encoding) {
2646#if 0
2647 // ARM pseudo code...
2648 if (ConditionPassed())
2649 {
2650 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2651 address = SP;
2652 SP = SP + imm32;
2653 if single_regs then
2654 for r = 0 to regs-1
2655 S[d+r] = MemA[address,4]; address = address+4;
2656 else
2657 for r = 0 to regs-1
2658 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
2659 // Combine the word-aligned words in the correct order for
2660 // current endianness.
2661 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
2662 }
2663#endif
2664
2665 bool success = false;
2666 if (ConditionPassed(opcode)) {
2667 const uint32_t addr_byte_size = GetAddressByteSize();
2668 const addr_t sp = ReadCoreReg(SP_REG, &success);
2669 if (!success)
2670 return false;
2671 bool single_regs;
2672 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2673 uint32_t imm32; // stack offset
2674 uint32_t regs; // number of registers
2675 switch (encoding) {
2676 case eEncodingT1:
2677 case eEncodingA1:
2678 single_regs = false;
2679 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
2680 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2681 // If UInt(imm8) is odd, see "FLDMX".
2682 regs = Bits32(opcode, 7, 0) / 2;
2683 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2684 if (regs == 0 || regs > 16 || (d + regs) > 32)
2685 return false;
2686 break;
2687 case eEncodingT2:
2688 case eEncodingA2:
2689 single_regs = true;
2690 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
2691 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2692 regs = Bits32(opcode, 7, 0);
2693 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2694 if (regs == 0 || regs > 16 || (d + regs) > 32)
2695 return false;
2696 break;
2697 default:
2698 return false;
2699 }
2700 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2701 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2702 addr_t sp_offset = imm32;
2703 addr_t addr = sp;
2704 uint32_t i;
2705 uint64_t data; // uint64_t to accommodate 64-bit registers.
2706
2709
2710 for (i = 0; i < regs; ++i) {
2711 std::optional<RegisterInfo> dwarf_reg =
2712 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i);
2713 context.SetAddress(addr);
2714 data = MemARead(context, addr, reg_byte_size, 0, &success);
2715 if (!success)
2716 return false;
2717 if (!WriteRegisterUnsigned(context, *dwarf_reg, data))
2718 return false;
2719 addr += reg_byte_size;
2720 }
2721
2723 context.SetImmediateSigned(sp_offset);
2724
2726 LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2727 return false;
2728 }
2729 return true;
2730}
2731
2732// SVC (previously SWI)
2733bool EmulateInstructionARM::EmulateSVC(const uint32_t opcode,
2734 const ARMEncoding encoding) {
2735#if 0
2736 // ARM pseudo code...
2737 if (ConditionPassed())
2738 {
2739 EncodingSpecificOperations();
2740 CallSupervisor();
2741 }
2742#endif
2743
2744 bool success = false;
2745
2746 if (ConditionPassed(opcode)) {
2747 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2748 addr_t lr; // next instruction address
2749 if (!success)
2750 return false;
2751 uint32_t imm32; // the immediate constant
2752 uint32_t mode; // ARM or Thumb mode
2753 switch (encoding) {
2754 case eEncodingT1:
2755 lr = (pc + 2) | 1u; // return address
2756 imm32 = Bits32(opcode, 7, 0);
2757 mode = eModeThumb;
2758 break;
2759 case eEncodingA1:
2760 lr = pc + 4; // return address
2761 imm32 = Bits32(opcode, 23, 0);
2762 mode = eModeARM;
2763 break;
2764 default:
2765 return false;
2766 }
2767
2770 context.SetISAAndImmediate(mode, imm32);
2773 return false;
2774 }
2775 return true;
2776}
2777
2778// If Then makes up to four following instructions (the IT block) conditional.
2779bool EmulateInstructionARM::EmulateIT(const uint32_t opcode,
2780 const ARMEncoding encoding) {
2781#if 0
2782 // ARM pseudo code...
2783 EncodingSpecificOperations();
2784 ITSTATE.IT<7:0> = firstcond:mask;
2785#endif
2786
2787 m_it_session.InitIT(Bits32(opcode, 7, 0));
2788 return true;
2789}
2790
2791bool EmulateInstructionARM::EmulateNop(const uint32_t opcode,
2792 const ARMEncoding encoding) {
2793 // NOP, nothing to do...
2794 return true;
2795}
2796
2797// Branch causes a branch to a target address.
2798bool EmulateInstructionARM::EmulateB(const uint32_t opcode,
2799 const ARMEncoding encoding) {
2800#if 0
2801 // ARM pseudo code...
2802 if (ConditionPassed())
2803 {
2804 EncodingSpecificOperations();
2805 BranchWritePC(PC + imm32);
2806 }
2807#endif
2808
2809 bool success = false;
2810
2811 if (ConditionPassed(opcode)) {
2814 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2815 if (!success)
2816 return false;
2817 addr_t target; // target address
2818 int32_t imm32; // PC-relative offset
2819 switch (encoding) {
2820 case eEncodingT1:
2821 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2822 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
2823 target = pc + imm32;
2824 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2825 break;
2826 case eEncodingT2:
2827 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0) << 1);
2828 target = pc + imm32;
2829 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2830 break;
2831 case eEncodingT3:
2832 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2833 {
2834 if (Bits32(opcode, 25, 23) == 7)
2835 return false; // See Branches and miscellaneous control on page
2836 // A6-235.
2837
2838 uint32_t S = Bit32(opcode, 26);
2839 uint32_t imm6 = Bits32(opcode, 21, 16);
2840 uint32_t J1 = Bit32(opcode, 13);
2841 uint32_t J2 = Bit32(opcode, 11);
2842 uint32_t imm11 = Bits32(opcode, 10, 0);
2843 uint32_t imm21 =
2844 (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
2845 imm32 = llvm::SignExtend32<21>(imm21);
2846 target = pc + imm32;
2847 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2848 break;
2849 }
2850 case eEncodingT4: {
2851 uint32_t S = Bit32(opcode, 26);
2852 uint32_t imm10 = Bits32(opcode, 25, 16);
2853 uint32_t J1 = Bit32(opcode, 13);
2854 uint32_t J2 = Bit32(opcode, 11);
2855 uint32_t imm11 = Bits32(opcode, 10, 0);
2856 uint32_t I1 = !(J1 ^ S);
2857 uint32_t I2 = !(J2 ^ S);
2858 uint32_t imm25 =
2859 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
2860 imm32 = llvm::SignExtend32<25>(imm25);
2861 target = pc + imm32;
2862 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2863 break;
2864 }
2865 case eEncodingA1:
2866 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
2867 target = pc + imm32;
2868 context.SetISAAndImmediateSigned(eModeARM, 8 + imm32);
2869 break;
2870 default:
2871 return false;
2872 }
2873 if (!BranchWritePC(context, target))
2874 return false;
2875 }
2876 return true;
2877}
2878
2879// Compare and Branch on Nonzero and Compare and Branch on Zero compare the
2880// value in a register with zero and conditionally branch forward a constant
2881// value. They do not affect the condition flags. CBNZ, CBZ
2882bool EmulateInstructionARM::EmulateCB(const uint32_t opcode,
2883 const ARMEncoding encoding) {
2884#if 0
2885 // ARM pseudo code...
2886 EncodingSpecificOperations();
2887 if nonzero ^ IsZero(R[n]) then
2888 BranchWritePC(PC + imm32);
2889#endif
2890
2891 bool success = false;
2892
2893 // Read the register value from the operand register Rn.
2894 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
2895 if (!success)
2896 return false;
2897
2900 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2901 if (!success)
2902 return false;
2903
2904 addr_t target; // target address
2905 uint32_t imm32; // PC-relative offset to branch forward
2906 bool nonzero;
2907 switch (encoding) {
2908 case eEncodingT1:
2909 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
2910 nonzero = BitIsSet(opcode, 11);
2911 target = pc + imm32;
2912 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2913 break;
2914 default:
2915 return false;
2916 }
2917 if (m_ignore_conditions || (nonzero ^ (reg_val == 0)))
2918 if (!BranchWritePC(context, target))
2919 return false;
2920
2921 return true;
2922}
2923
2924// Table Branch Byte causes a PC-relative forward branch using a table of
2925// single byte offsets.
2926// A base register provides a pointer to the table, and a second register
2927// supplies an index into the table.
2928// The branch length is twice the value of the byte returned from the table.
2929//
2930// Table Branch Halfword causes a PC-relative forward branch using a table of
2931// single halfword offsets.
2932// A base register provides a pointer to the table, and a second register
2933// supplies an index into the table.
2934// The branch length is twice the value of the halfword returned from the
2935// table. TBB, TBH
2936bool EmulateInstructionARM::EmulateTB(const uint32_t opcode,
2937 const ARMEncoding encoding) {
2938#if 0
2939 // ARM pseudo code...
2940 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2941 if is_tbh then
2942 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2943 else
2944 halfwords = UInt(MemU[R[n]+R[m], 1]);
2945 BranchWritePC(PC + 2*halfwords);
2946#endif
2947
2948 bool success = false;
2949
2950 if (ConditionPassed(opcode)) {
2951 uint32_t Rn; // the base register which contains the address of the table of
2952 // branch lengths
2953 uint32_t Rm; // the index register which contains an integer pointing to a
2954 // byte/halfword in the table
2955 bool is_tbh; // true if table branch halfword
2956 switch (encoding) {
2957 case eEncodingT1:
2958 Rn = Bits32(opcode, 19, 16);
2959 Rm = Bits32(opcode, 3, 0);
2960 is_tbh = BitIsSet(opcode, 4);
2961 if (Rn == 13 || BadReg(Rm))
2962 return false;
2963 if (InITBlock() && !LastInITBlock())
2964 return false;
2965 break;
2966 default:
2967 return false;
2968 }
2969
2970 // Read the address of the table from the operand register Rn. The PC can
2971 // be used, in which case the table immediately follows this instruction.
2972 uint32_t base = ReadCoreReg(Rn, &success);
2973 if (!success)
2974 return false;
2975
2976 // the table index
2977 uint32_t index = ReadCoreReg(Rm, &success);
2978 if (!success)
2979 return false;
2980
2981 // the offsetted table address
2982 addr_t addr = base + (is_tbh ? index * 2 : index);
2983
2984 // PC-relative offset to branch forward
2987 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
2988 if (!success)
2989 return false;
2990
2991 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2992 if (!success)
2993 return false;
2994
2995 // target address
2996 addr_t target = pc + offset;
2998 context.SetISAAndImmediateSigned(eModeThumb, 4 + offset);
2999
3000 if (!BranchWritePC(context, target))
3001 return false;
3002 }
3003
3004 return true;
3005}
3006
3007// This instruction adds an immediate value to a register value, and writes the
3008// result to the destination register. It can optionally update the condition
3009// flags based on the result.
3011 const ARMEncoding encoding) {
3012#if 0
3013 if ConditionPassed() then
3014 EncodingSpecificOperations();
3015 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3016 R[d] = result;
3017 if setflags then
3018 APSR.N = result<31>;
3019 APSR.Z = IsZeroBit(result);
3020 APSR.C = carry;
3021 APSR.V = overflow;
3022#endif
3023
3024 bool success = false;
3025
3026 if (ConditionPassed(opcode)) {
3027 uint32_t d;
3028 uint32_t n;
3029 bool setflags;
3030 uint32_t imm32;
3031 uint32_t carry_out;
3032
3033 // EncodingSpecificOperations();
3034 switch (encoding) {
3035 case eEncodingT1:
3036 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 =
3037 // ZeroExtend(imm3, 32);
3038 d = Bits32(opcode, 2, 0);
3039 n = Bits32(opcode, 5, 3);
3040 setflags = !InITBlock();
3041 imm32 = Bits32(opcode, 8, 6);
3042
3043 break;
3044
3045 case eEncodingT2:
3046 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 =
3047 // ZeroExtend(imm8, 32);
3048 d = Bits32(opcode, 10, 8);
3049 n = Bits32(opcode, 10, 8);
3050 setflags = !InITBlock();
3051 imm32 = Bits32(opcode, 7, 0);
3052
3053 break;
3054
3055 case eEncodingT3:
3056 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
3057 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 =
3058 // ThumbExpandImm(i:imm3:imm8);
3059 d = Bits32(opcode, 11, 8);
3060 n = Bits32(opcode, 19, 16);
3061 setflags = BitIsSet(opcode, 20);
3062 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry_out);
3063
3064 // if Rn == '1101' then SEE ADD (SP plus immediate);
3065 if (n == 13)
3066 return EmulateADDSPImm(opcode, eEncodingT3);
3067
3068 // if BadReg(d) || n == 15 then UNPREDICTABLE;
3069 if (BadReg(d) || (n == 15))
3070 return false;
3071
3072 break;
3073
3074 case eEncodingT4: {
3075 // if Rn == '1111' then SEE ADR;
3076 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 =
3077 // ZeroExtend(i:imm3:imm8, 32);
3078 d = Bits32(opcode, 11, 8);
3079 n = Bits32(opcode, 19, 16);
3080 setflags = false;
3081 uint32_t i = Bit32(opcode, 26);
3082 uint32_t imm3 = Bits32(opcode, 14, 12);
3083 uint32_t imm8 = Bits32(opcode, 7, 0);
3084 imm32 = (i << 11) | (imm3 << 8) | imm8;
3085
3086 // if Rn == '1101' then SEE ADD (SP plus immediate);
3087 if (n == 13)
3088 return EmulateADDSPImm(opcode, eEncodingT4);
3089
3090 // if BadReg(d) then UNPREDICTABLE;
3091 if (BadReg(d))
3092 return false;
3093
3094 break;
3095 }
3096
3097 default:
3098 return false;
3099 }
3100
3101 uint64_t Rn =
3103 if (!success)
3104 return false;
3105
3106 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3107 AddWithCarryResult res = AddWithCarry(Rn, imm32, 0);
3108
3109 std::optional<RegisterInfo> reg_n =
3112 context.type = eContextArithmetic;
3113 context.SetRegisterPlusOffset(*reg_n, imm32);
3114
3115 // R[d] = result;
3116 // if setflags then
3117 // APSR.N = result<31>;
3118 // APSR.Z = IsZeroBit(result);
3119 // APSR.C = carry;
3120 // APSR.V = overflow;
3121 if (!WriteCoreRegOptionalFlags(context, res.result, d, setflags,
3122 res.carry_out, res.overflow))
3123 return false;
3124 }
3125 return true;
3126}
3127
3128// This instruction adds an immediate value to a register value, and writes the
3129// result to the destination register. It can optionally update the condition
3130// flags based on the result.
3132 const ARMEncoding encoding) {
3133#if 0
3134 // ARM pseudo code...
3135 if ConditionPassed() then
3136 EncodingSpecificOperations();
3137 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3138 if d == 15 then
3139 ALUWritePC(result); // setflags is always FALSE here
3140 else
3141 R[d] = result;
3142 if setflags then
3143 APSR.N = result<31>;
3144 APSR.Z = IsZeroBit(result);
3145 APSR.C = carry;
3146 APSR.V = overflow;
3147#endif
3148
3149 bool success = false;
3150
3151 if (ConditionPassed(opcode)) {
3152 uint32_t Rd, Rn;
3153 uint32_t
3154 imm32; // the immediate value to be added to the value obtained from Rn
3155 bool setflags;
3156 switch (encoding) {
3157 case eEncodingA1:
3158 Rd = Bits32(opcode, 15, 12);
3159 Rn = Bits32(opcode, 19, 16);
3160 setflags = BitIsSet(opcode, 20);
3161 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3162 break;
3163 default:
3164 return false;
3165 }
3166
3167 // Read the first operand.
3168 uint32_t val1 = ReadCoreReg(Rn, &success);
3169 if (!success)
3170 return false;
3171
3172 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
3173
3175 if (Rd == 13)
3177 else if (Rd == GetFramePointerRegisterNumber())
3179 else
3181
3182 std::optional<RegisterInfo> dwarf_reg =
3184 context.SetRegisterPlusOffset(*dwarf_reg, imm32);
3185
3186 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
3187 res.carry_out, res.overflow))
3188 return false;
3189 }
3190 return true;
3191}
3192
3193// This instruction adds a register value and an optionally-shifted register
3194// value, and writes the result to the destination register. It can optionally
3195// update the condition flags based on the result.
3196bool EmulateInstructionARM::EmulateADDReg(const uint32_t opcode,
3197 const ARMEncoding encoding) {
3198#if 0
3199 // ARM pseudo code...
3200 if ConditionPassed() then
3201 EncodingSpecificOperations();
3202 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
3203 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
3204 if d == 15 then
3205 ALUWritePC(result); // setflags is always FALSE here
3206 else
3207 R[d] = result;
3208 if setflags then
3209 APSR.N = result<31>;
3210 APSR.Z = IsZeroBit(result);
3211 APSR.C = carry;
3212 APSR.V = overflow;
3213#endif
3214
3215 bool success = false;
3216
3217 if (ConditionPassed(opcode)) {
3218 uint32_t Rd, Rn, Rm;
3219 ARM_ShifterType shift_t;
3220 uint32_t shift_n; // the shift applied to the value read from Rm
3221 bool setflags;
3222 switch (encoding) {
3223 case eEncodingT1:
3224 Rd = Bits32(opcode, 2, 0);
3225 Rn = Bits32(opcode, 5, 3);
3226 Rm = Bits32(opcode, 8, 6);
3227 setflags = !InITBlock();
3228 shift_t = SRType_LSL;
3229 shift_n = 0;
3230 break;
3231 case eEncodingT2:
3232 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
3233 Rm = Bits32(opcode, 6, 3);
3234 setflags = false;
3235 shift_t = SRType_LSL;
3236 shift_n = 0;
3237 if (Rn == 15 && Rm == 15)
3238 return false;
3239 if (Rd == 15 && InITBlock() && !LastInITBlock())
3240 return false;
3241 break;
3242 case eEncodingA1:
3243 Rd = Bits32(opcode, 15, 12);
3244 Rn = Bits32(opcode, 19, 16);
3245 Rm = Bits32(opcode, 3, 0);
3246 setflags = BitIsSet(opcode, 20);
3247 shift_n = DecodeImmShiftARM(opcode, shift_t);
3248 break;
3249 default:
3250 return false;
3251 }
3252
3253 // Read the first operand.
3254 uint32_t val1 = ReadCoreReg(Rn, &success);
3255 if (!success)
3256 return false;
3257
3258 // Read the second operand.
3259 uint32_t val2 = ReadCoreReg(Rm, &success);
3260 if (!success)
3261 return false;
3262
3263 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
3264 if (!success)
3265 return false;
3266 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
3267
3269 context.type = eContextArithmetic;
3270 std::optional<RegisterInfo> op1_reg =
3272 std::optional<RegisterInfo> op2_reg =
3274 context.SetRegisterRegisterOperands(*op1_reg, *op2_reg);
3275
3276 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
3277 res.carry_out, res.overflow))
3278 return false;
3279 }
3280 return true;
3281}
3282
3283// Compare Negative (immediate) adds a register value and an immediate value.
3284// It updates the condition flags based on the result, and discards the result.
3285bool EmulateInstructionARM::EmulateCMNImm(const uint32_t opcode,
3286 const ARMEncoding encoding) {
3287#if 0
3288 // ARM pseudo code...
3289 if ConditionPassed() then
3290 EncodingSpecificOperations();
3291 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3292 APSR.N = result<31>;
3293 APSR.Z = IsZeroBit(result);
3294 APSR.C = carry;
3295 APSR.V = overflow;
3296#endif
3297
3298 bool success = false;
3299
3300 uint32_t Rn; // the first operand
3301 uint32_t imm32; // the immediate value to be compared with
3302 switch (encoding) {
3303 case eEncodingT1:
3304 Rn = Bits32(opcode, 19, 16);
3305 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
3306 if (Rn == 15)
3307 return false;
3308 break;
3309 case eEncodingA1:
3310 Rn = Bits32(opcode, 19, 16);
3311 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3312 break;
3313 default:
3314 return false;
3315 }
3316 // Read the register value from the operand register Rn.
3317 uint32_t reg_val = ReadCoreReg(Rn, &success);
3318 if (!success)
3319 return false;
3320
3321 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
3322
3325 context.SetNoArgs();
3326 return WriteFlags(context, res.result, res.carry_out, res.overflow);
3327}
3328
3329// Compare Negative (register) adds a register value and an optionally-shifted
3330// register value. It updates the condition flags based on the result, and
3331// discards the result.
3332bool EmulateInstructionARM::EmulateCMNReg(const uint32_t opcode,
3333 const ARMEncoding encoding) {
3334#if 0
3335 // ARM pseudo code...
3336 if ConditionPassed() then
3337 EncodingSpecificOperations();
3338 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
3339 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
3340 APSR.N = result<31>;
3341 APSR.Z = IsZeroBit(result);
3342 APSR.C = carry;
3343 APSR.V = overflow;
3344#endif
3345
3346 bool success = false;
3347
3348 uint32_t Rn; // the first operand
3349 uint32_t Rm; // the second operand
3350 ARM_ShifterType shift_t;
3351 uint32_t shift_n; // the shift applied to the value read from Rm
3352 switch (encoding) {
3353 case eEncodingT1:
3354 Rn = Bits32(opcode, 2, 0);
3355 Rm = Bits32(opcode, 5, 3);
3356 shift_t = SRType_LSL;
3357 shift_n = 0;
3358 break;
3359 case eEncodingT2:
3360 Rn = Bits32(opcode, 19, 16);
3361 Rm = Bits32(opcode, 3, 0);
3362 shift_n = DecodeImmShiftThumb(opcode, shift_t);
3363 // if n == 15 || BadReg(m) then UNPREDICTABLE;
3364 if (Rn == 15 || BadReg(Rm))
3365 return false;
3366 break;
3367 case eEncodingA1:
3368 Rn = Bits32(opcode, 19, 16);
3369 Rm = Bits32(opcode, 3, 0);
3370 shift_n = DecodeImmShiftARM(opcode, shift_t);
3371 break;
3372 default:
3373 return false;
3374 }
3375 // Read the register value from register Rn.
3376 uint32_t val1 = ReadCoreReg(Rn, &success);
3377 if (!success)
3378 return false;
3379
3380 // Read the register value from register Rm.
3381 uint32_t val2 = ReadCoreReg(Rm, &success);
3382 if (!success)
3383 return false;
3384
3385 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
3386 if (!success)
3387 return false;
3388 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
3389
3392 context.SetNoArgs();
3393 return WriteFlags(context, res.result, res.carry_out, res.overflow);
3394}
3395
3396// Compare (immediate) subtracts an immediate value from a register value. It
3397// updates the condition flags based on the result, and discards the result.
3398bool EmulateInstructionARM::EmulateCMPImm(const uint32_t opcode,
3399 const ARMEncoding encoding) {
3400#if 0
3401 // ARM pseudo code...
3402 if ConditionPassed() then
3403 EncodingSpecificOperations();
3404 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
3405 APSR.N = result<31>;
3406 APSR.Z = IsZeroBit(result);
3407 APSR.C = carry;
3408 APSR.V = overflow;
3409#endif
3410
3411 bool success = false;
3412
3413 uint32_t Rn; // the first operand
3414 uint32_t imm32; // the immediate value to be compared with
3415 switch (encoding) {
3416 case eEncodingT1:
3417 Rn = Bits32(opcode, 10, 8);
3418 imm32 = Bits32(opcode, 7, 0);
3419 break;
3420 case eEncodingT2:
3421 Rn = Bits32(opcode, 19, 16);
3422 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
3423 if (Rn == 15)
3424 return false;
3425 break;
3426 case eEncodingA1:
3427 Rn = Bits32(opcode, 19, 16);
3428 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3429 break;
3430 default:
3431 return false;
3432 }
3433 // Read the register value from the operand register Rn.
3434 uint32_t reg_val = ReadCoreReg(Rn, &success);
3435 if (!success)
3436 return false;
3437
3438 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
3439
3442 context.SetNoArgs();
3443 return WriteFlags(context, res.result, res.carry_out, res.overflow);
3444}
3445
3446// Compare (register) subtracts an optionally-shifted register value from a
3447// register value. It updates the condition flags based on the result, and
3448// discards the result.
3449bool EmulateInstructionARM::EmulateCMPReg(const uint32_t opcode,
3450 const ARMEncoding encoding) {
3451#if 0
3452 // ARM pseudo code...
3453 if ConditionPassed() then
3454 EncodingSpecificOperations();
3455 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
3456 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
3457 APSR.N = result<31>;
3458 APSR.Z = IsZeroBit(result);
3459 APSR.C = carry;
3460 APSR.V = overflow;
3461#endif
3462
3463 bool success = false;
3464
3465 uint32_t Rn; // the first operand
3466 uint32_t Rm; // the second operand
3467 ARM_ShifterType shift_t;
3468 uint32_t shift_n; // the shift applied to the value read from Rm
3469 switch (encoding) {
3470 case eEncodingT1:
3471 Rn = Bits32(opcode, 2, 0);
3472 Rm = Bits32(opcode, 5, 3);
3473 shift_t = SRType_LSL;
3474 shift_n = 0;
3475 break;
3476 case eEncodingT2:
3477 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
3478 Rm = Bits32(opcode, 6, 3);
3479 shift_t = SRType_LSL;
3480 shift_n = 0;
3481 if (Rn < 8 && Rm < 8)
3482 return false;
3483 if (Rn == 15 || Rm == 15)
3484 return false;
3485 break;
3486 case eEncodingT3:
3487 Rn = Bits32(opcode, 19, 16);
3488 Rm = Bits32(opcode, 3, 0);
3489 shift_n = DecodeImmShiftThumb(opcode, shift_t);
3490 if (Rn == 15 || BadReg(Rm))
3491 return false;
3492 break;
3493 case eEncodingA1:
3494 Rn = Bits32(opcode, 19, 16);
3495 Rm = Bits32(opcode, 3, 0);
3496 shift_n = DecodeImmShiftARM(opcode, shift_t);
3497 break;
3498 default:
3499 return false;
3500 }
3501 // Read the register value from register Rn.
3502 uint32_t val1 = ReadCoreReg(Rn, &success);
3503 if (!success)
3504 return false;
3505
3506 // Read the register value from register Rm.
3507 uint32_t val2 = ReadCoreReg(Rm, &success);
3508 if (!success)
3509 return false;
3510
3511 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
3512 if (!success)
3513 return false;
3514 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
3515
3518 context.SetNoArgs();
3519 return WriteFlags(context, res.result, res.carry_out, res.overflow);
3520}
3521
3522// Arithmetic Shift Right (immediate) shifts a register value right by an
3523// immediate number of bits, shifting in copies of its sign bit, and writes the
3524// result to the destination register. It can optionally update the condition
3525// flags based on the result.
3526bool EmulateInstructionARM::EmulateASRImm(const uint32_t opcode,
3527 const ARMEncoding encoding) {
3528#if 0
3529 // ARM pseudo code...
3530 if ConditionPassed() then
3531 EncodingSpecificOperations();
3532 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
3533 if d == 15 then // Can only occur for ARM encoding
3534 ALUWritePC(result); // setflags is always FALSE here
3535 else
3536 R[d] = result;
3537 if setflags then
3538 APSR.N = result<31>;
3539 APSR.Z = IsZeroBit(result);
3540 APSR.C = carry;
3541 // APSR.V unchanged
3542#endif
3543
3544 return EmulateShiftImm(opcode, encoding, SRType_ASR);
3545}
3546
3547// Arithmetic Shift Right (register) shifts a register value right by a
3548// variable number of bits, shifting in copies of its sign bit, and writes the
3549// result to the destination register. The variable number of bits is read from
3550// the bottom byte of a register. It can optionally update the condition flags
3551// based on the result.
3552bool EmulateInstructionARM::EmulateASRReg(const uint32_t opcode,
3553 const ARMEncoding encoding) {
3554#if 0
3555 // ARM pseudo code...
3556 if ConditionPassed() then
3557 EncodingSpecificOperations();
3558 shift_n = UInt(R[m]<7:0>);
3559 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
3560 R[d] = result;
3561 if setflags then
3562 APSR.N = result<31>;
3563 APSR.Z = IsZeroBit(result);
3564 APSR.C = carry;
3565 // APSR.V unchanged
3566#endif
3567
3568 return EmulateShiftReg(opcode, encoding, SRType_ASR);
3569}
3570
3571// Logical Shift Left (immediate) shifts a register value left by an immediate
3572// number of bits, shifting in zeros, and writes the result to the destination
3573// register. It can optionally update the condition flags based on the result.
3574bool EmulateInstructionARM::EmulateLSLImm(const uint32_t opcode,
3575 const ARMEncoding encoding) {
3576#if 0
3577 // ARM pseudo code...
3578 if ConditionPassed() then
3579 EncodingSpecificOperations();
3580 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
3581 if d == 15 then // Can only occur for ARM encoding
3582 ALUWritePC(result); // setflags is always FALSE here
3583 else
3584 R[d] = result;
3585 if setflags then
3586 APSR.N = result<31>;
3587 APSR.Z = IsZeroBit(result);
3588 APSR.C = carry;
3589 // APSR.V unchanged
3590#endif
3591
3592 return EmulateShiftImm(opcode, encoding, SRType_LSL);
3593}
3594
3595// Logical Shift Left (register) shifts a register value left by a variable
3596// number of bits, shifting in zeros, and writes the result to the destination
3597// register. The variable number of bits is read from the bottom byte of a
3598// register. It can optionally update the condition flags based on the result.
3599bool EmulateInstructionARM::EmulateLSLReg(const uint32_t opcode,
3600 const ARMEncoding encoding) {
3601#if 0
3602 // ARM pseudo code...
3603 if ConditionPassed() then
3604 EncodingSpecificOperations();
3605 shift_n = UInt(R[m]<7:0>);
3606 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
3607 R[d] = result;
3608 if setflags then
3609 APSR.N = result<31>;
3610 APSR.Z = IsZeroBit(result);
3611 APSR.C = carry;
3612 // APSR.V unchanged
3613#endif
3614
3615 return EmulateShiftReg(opcode, encoding, SRType_LSL);
3616}
3617
3618// Logical Shift Right (immediate) shifts a register value right by an
3619// immediate number of bits, shifting in zeros, and writes the result to the
3620// destination register. It can optionally update the condition flags based on
3621// the result.
3622bool EmulateInstructionARM::EmulateLSRImm(const uint32_t opcode,
3623 const ARMEncoding encoding) {
3624#if 0
3625 // ARM pseudo code...
3626 if ConditionPassed() then
3627 EncodingSpecificOperations();
3628 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3629 if d == 15 then // Can only occur for ARM encoding
3630 ALUWritePC(result); // setflags is always FALSE here
3631 else
3632 R[d] = result;
3633 if setflags then
3634 APSR.N = result<31>;
3635 APSR.Z = IsZeroBit(result);
3636 APSR.C = carry;
3637 // APSR.V unchanged
3638#endif
3639
3640 return EmulateShiftImm(opcode, encoding, SRType_LSR);
3641}
3642
3643// Logical Shift Right (register) shifts a register value right by a variable
3644// number of bits, shifting in zeros, and writes the result to the destination
3645// register. The variable number of bits is read from the bottom byte of a
3646// register. It can optionally update the condition flags based on the result.
3647bool EmulateInstructionARM::EmulateLSRReg(const uint32_t opcode,
3648 const ARMEncoding encoding) {
3649#if 0
3650 // ARM pseudo code...
3651 if ConditionPassed() then
3652 EncodingSpecificOperations();
3653 shift_n = UInt(R[m]<7:0>);
3654 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3655 R[d] = result;
3656 if setflags then
3657 APSR.N = result<31>;
3658 APSR.Z = IsZeroBit(result);
3659 APSR.C = carry;
3660 // APSR.V unchanged
3661#endif
3662
3663 return EmulateShiftReg(opcode, encoding, SRType_LSR);
3664}
3665
3666// Rotate Right (immediate) provides the value of the contents of a register
3667// rotated by a constant value. The bits that are rotated off the right end are
3668// inserted into the vacated bit positions on the left. It can optionally
3669// update the condition flags based on the result.
3670bool EmulateInstructionARM::EmulateRORImm(const uint32_t opcode,
3671 const ARMEncoding encoding) {
3672#if 0
3673 // ARM pseudo code...
3674 if ConditionPassed() then
3675 EncodingSpecificOperations();
3676 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3677 if d == 15 then // Can only occur for ARM encoding
3678 ALUWritePC(result); // setflags is always FALSE here
3679 else
3680 R[d] = result;
3681 if setflags then
3682 APSR.N = result<31>;
3683 APSR.Z = IsZeroBit(result);
3684 APSR.C = carry;
3685 // APSR.V unchanged
3686#endif
3687
3688 return EmulateShiftImm(opcode, encoding, SRType_ROR);
3689}
3690
3691// Rotate Right (register) provides the value of the contents of a register
3692// rotated by a variable number of bits. The bits that are rotated off the
3693// right end are inserted into the vacated bit positions on the left. The
3694// variable number of bits is read from the bottom byte of a register. It can
3695// optionally update the condition flags based on the result.
3696bool EmulateInstructionARM::EmulateRORReg(const uint32_t opcode,
3697 const ARMEncoding encoding) {
3698#if 0
3699 // ARM pseudo code...
3700 if ConditionPassed() then
3701 EncodingSpecificOperations();
3702 shift_n = UInt(R[m]<7:0>);
3703 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3704 R[d] = result;
3705 if setflags then
3706 APSR.N = result<31>;
3707 APSR.Z = IsZeroBit(result);
3708 APSR.C = carry;
3709 // APSR.V unchanged
3710#endif
3711
3712 return EmulateShiftReg(opcode, encoding, SRType_ROR);
3713}
3714
3715// Rotate Right with Extend provides the value of the contents of a register
3716// shifted right by one place, with the carry flag shifted into bit [31].
3717//
3718// RRX can optionally update the condition flags based on the result.
3719// In that case, bit [0] is shifted into the carry flag.
3720bool EmulateInstructionARM::EmulateRRX(const uint32_t opcode,
3721 const ARMEncoding encoding) {
3722#if 0
3723 // ARM pseudo code...
3724 if ConditionPassed() then
3725 EncodingSpecificOperations();
3726 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3727 if d == 15 then // Can only occur for ARM encoding
3728 ALUWritePC(result); // setflags is always FALSE here
3729 else
3730 R[d] = result;
3731 if setflags then
3732 APSR.N = result<31>;
3733 APSR.Z = IsZeroBit(result);
3734 APSR.C = carry;
3735 // APSR.V unchanged
3736#endif
3737
3738 return EmulateShiftImm(opcode, encoding, SRType_RRX);
3739}
3740
3742 const ARMEncoding encoding,
3743 ARM_ShifterType shift_type) {
3744 // assert(shift_type == SRType_ASR
3745 // || shift_type == SRType_LSL
3746 // || shift_type == SRType_LSR
3747 // || shift_type == SRType_ROR
3748 // || shift_type == SRType_RRX);
3749
3750 bool success = false;
3751
3752 if (ConditionPassed(opcode)) {
3753 uint32_t Rd; // the destination register
3754 uint32_t Rm; // the first operand register
3755 uint32_t imm5; // encoding for the shift amount
3756 uint32_t carry; // the carry bit after the shift operation
3757 bool setflags;
3758
3759 // Special case handling!
3760 // A8.6.139 ROR (immediate) -- Encoding T1
3761 ARMEncoding use_encoding = encoding;
3762 if (shift_type == SRType_ROR && use_encoding == eEncodingT1) {
3763 // Morph the T1 encoding from the ARM Architecture Manual into T2
3764 // encoding to have the same decoding of bit fields as the other Thumb2
3765 // shift operations.
3766 use_encoding = eEncodingT2;
3767 }
3768
3769 switch (use_encoding) {
3770 case eEncodingT1:
3771 Rd = Bits32(opcode, 2, 0);
3772 Rm = Bits32(opcode, 5, 3);
3773 setflags = !InITBlock();
3774 imm5 = Bits32(opcode, 10, 6);
3775 break;
3776 case eEncodingT2:
3777 // A8.6.141 RRX
3778 // There's no imm form of RRX instructions.
3779 if (shift_type == SRType_RRX)
3780 return false;
3781
3782 Rd = Bits32(opcode, 11, 8);
3783 Rm = Bits32(opcode, 3, 0);
3784 setflags = BitIsSet(opcode, 20);
3785 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3786 if (BadReg(Rd) || BadReg(Rm))
3787 return false;
3788 break;
3789 case eEncodingA1:
3790 Rd = Bits32(opcode, 15, 12);
3791 Rm = Bits32(opcode, 3, 0);
3792 setflags = BitIsSet(opcode, 20);
3793 imm5 = Bits32(opcode, 11, 7);
3794 break;
3795 default:
3796 return false;
3797 }
3798
3799 // A8.6.139 ROR (immediate)
3800 if (shift_type == SRType_ROR && imm5 == 0)
3801 shift_type = SRType_RRX;
3802
3803 // Get the first operand.
3804 uint32_t value = ReadCoreReg(Rm, &success);
3805 if (!success)
3806 return false;
3807
3808 // Decode the shift amount if not RRX.
3809 uint32_t amt =
3810 (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
3811
3812 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3813 if (!success)
3814 return false;
3815
3816 // The context specifies that an immediate is to be moved into Rd.
3819 context.SetNoArgs();
3820
3821 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3822 return false;
3823 }
3824 return true;
3825}
3826
3828 const ARMEncoding encoding,
3829 ARM_ShifterType shift_type) {
3830 // assert(shift_type == SRType_ASR
3831 // || shift_type == SRType_LSL
3832 // || shift_type == SRType_LSR
3833 // || shift_type == SRType_ROR);
3834
3835 bool success = false;
3836
3837 if (ConditionPassed(opcode)) {
3838 uint32_t Rd; // the destination register
3839 uint32_t Rn; // the first operand register
3840 uint32_t
3841 Rm; // the register whose bottom byte contains the amount to shift by
3842 uint32_t carry; // the carry bit after the shift operation
3843 bool setflags;
3844 switch (encoding) {
3845 case eEncodingT1:
3846 Rd = Bits32(opcode, 2, 0);
3847 Rn = Rd;
3848 Rm = Bits32(opcode, 5, 3);
3849 setflags = !InITBlock();
3850 break;
3851 case eEncodingT2:
3852 Rd = Bits32(opcode, 11, 8);
3853 Rn = Bits32(opcode, 19, 16);
3854 Rm = Bits32(opcode, 3, 0);
3855 setflags = BitIsSet(opcode, 20);
3856 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3857 return false;
3858 break;
3859 case eEncodingA1:
3860 Rd = Bits32(opcode, 15, 12);
3861 Rn = Bits32(opcode, 3, 0);
3862 Rm = Bits32(opcode, 11, 8);
3863 setflags = BitIsSet(opcode, 20);
3864 if (Rd == 15 || Rn == 15 || Rm == 15)
3865 return false;
3866 break;
3867 default:
3868 return false;
3869 }
3870
3871 // Get the first operand.
3872 uint32_t value = ReadCoreReg(Rn, &success);
3873 if (!success)
3874 return false;
3875 // Get the Rm register content.
3876 uint32_t val = ReadCoreReg(Rm, &success);
3877 if (!success)
3878 return false;
3879
3880 // Get the shift amount.
3881 uint32_t amt = Bits32(val, 7, 0);
3882
3883 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3884 if (!success)
3885 return false;
3886
3887 // The context specifies that an immediate is to be moved into Rd.
3890 context.SetNoArgs();
3891
3892 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3893 return false;
3894 }
3895 return true;
3896}
3897
3898// LDM loads multiple registers from consecutive memory locations, using an
3899// address from a base register. Optionally the address just above the highest
3900// of those locations can be written back to the base register.
3901bool EmulateInstructionARM::EmulateLDM(const uint32_t opcode,
3902 const ARMEncoding encoding) {
3903#if 0
3904 // ARM pseudo code...
3905 if ConditionPassed()
3906 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3907 address = R[n];
3908
3909 for i = 0 to 14
3910 if registers<i> == '1' then
3911 R[i] = MemA[address, 4]; address = address + 4;
3912 if registers<15> == '1' then
3913 LoadWritePC (MemA[address, 4]);
3914
3915 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3916 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3917
3918#endif
3919
3920 bool success = false;
3921 if (ConditionPassed(opcode)) {
3922 uint32_t n;
3923 uint32_t registers = 0;
3924 bool wback;
3925 const uint32_t addr_byte_size = GetAddressByteSize();
3926 switch (encoding) {
3927 case eEncodingT1:
3928 // n = UInt(Rn); registers = '00000000':register_list; wback =
3929 // (registers<n> == '0');
3930 n = Bits32(opcode, 10, 8);
3931 registers = Bits32(opcode, 7, 0);
3932 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
3933 wback = BitIsClear(registers, n);
3934 // if BitCount(registers) < 1 then UNPREDICTABLE;
3935 if (BitCount(registers) < 1)
3936 return false;
3937 break;
3938 case eEncodingT2:
3939 // if W == '1' && Rn == '1101' then SEE POP;
3940 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
3941 n = Bits32(opcode, 19, 16);
3942 registers = Bits32(opcode, 15, 0);
3943 registers = registers & 0xdfff; // Make sure bit 13 is zero.
3944 wback = BitIsSet(opcode, 21);
3945
3946 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then
3947 // UNPREDICTABLE;
3948 if ((n == 15) || (BitCount(registers) < 2) ||
3949 (BitIsSet(opcode, 14) && BitIsSet(opcode, 15)))
3950 return false;
3951
3952 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
3953 // UNPREDICTABLE;
3954 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
3955 return false;
3956
3957 // if wback && registers<n> == '1' then UNPREDICTABLE;
3958 if (wback && BitIsSet(registers, n))
3959 return false;
3960 break;
3961
3962 case eEncodingA1:
3963 n = Bits32(opcode, 19, 16);
3964 registers = Bits32(opcode, 15, 0);
3965 wback = BitIsSet(opcode, 21);
3966 if ((n == 15) || (BitCount(registers) < 1))
3967 return false;
3968 break;
3969 default:
3970 return false;
3971 }
3972
3973 int32_t offset = 0;
3974 const addr_t base_address =
3976 if (!success)
3977 return false;
3978
3981 std::optional<RegisterInfo> dwarf_reg =
3983 context.SetRegisterPlusOffset(*dwarf_reg, offset);
3984
3985 for (int i = 0; i < 14; ++i) {
3986 if (BitIsSet(registers, i)) {
3988 context.SetRegisterPlusOffset(*dwarf_reg, offset);
3989 if (wback && (n == 13)) // Pop Instruction
3990 {
3992 context.SetAddress(base_address + offset);
3993 }
3994
3995 // R[i] = MemA [address, 4]; address = address + 4;
3996 uint32_t data = MemARead(context, base_address + offset, addr_byte_size,
3997 0, &success);
3998 if (!success)
3999 return false;
4000
4002 data))
4003 return false;
4004
4005 offset += addr_byte_size;
4006 }
4007 }
4008
4009 if (BitIsSet(registers, 15)) {
4010 // LoadWritePC (MemA [address, 4]);
4012 context.SetRegisterPlusOffset(*dwarf_reg, offset);
4013 uint32_t data =
4014 MemARead(context, base_address + offset, addr_byte_size, 0, &success);
4015 if (!success)
4016 return false;
4017 // In ARMv5T and above, this is an interworking branch.
4018 if (!LoadWritePC(context, data))
4019 return false;
4020 }
4021
4022 if (wback && BitIsClear(registers, n)) {
4023 // R[n] = R[n] + 4 * BitCount (registers)
4024 int32_t offset = addr_byte_size * BitCount(registers);
4026 context.SetRegisterPlusOffset(*dwarf_reg, offset);
4027
4029 base_address + offset))
4030 return false;
4031 }
4032 if (wback && BitIsSet(registers, n))
4033 // R[n] bits(32) UNKNOWN;
4034 return WriteBits32Unknown(n);
4035 }
4036 return true;
4037}
4038
4039// LDMDA loads multiple registers from consecutive memory locations using an
4040// address from a base register.
4041// The consecutive memory locations end at this address and the address just
4042// below the lowest of those locations can optionally be written back to the
4043// base register.
4044bool EmulateInstructionARM::EmulateLDMDA(const uint32_t opcode,
4045 const ARMEncoding encoding) {
4046#if 0
4047 // ARM pseudo code...
4048 if ConditionPassed() then
4049 EncodingSpecificOperations();
4050 address = R[n] - 4*BitCount(registers) + 4;
4051
4052 for i = 0 to 14
4053 if registers<i> == '1' then
4054 R[i] = MemA[address,4]; address = address + 4;
4055
4056 if registers<15> == '1' then
4057 LoadWritePC(MemA[address,4]);
4058
4059 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4060 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4061#endif
4062
4063 bool success = false;
4064
4065 if (ConditionPassed(opcode)) {
4066 uint32_t n;
4067 uint32_t registers = 0;
4068 bool wback;
4069 const uint32_t addr_byte_size = GetAddressByteSize();
4070
4071 // EncodingSpecificOperations();
4072 switch (encoding) {
4073 case eEncodingA1:
4074 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4075 n = Bits32(opcode, 19, 16);
4076 registers = Bits32(opcode, 15, 0);
4077 wback = BitIsSet(opcode, 21);
4078
4079 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4080 if ((n == 15) || (BitCount(registers) < 1))
4081 return false;
4082
4083 break;
4084
4085 default:
4086 return false;
4087 }
4088 // address = R[n] - 4*BitCount(registers) + 4;
4089
4090 int32_t offset = 0;
4091 addr_t Rn = ReadCoreReg(n, &success);
4092
4093 if (!success)
4094 return false;
4095
4096 addr_t address =
4097 Rn - (addr_byte_size * BitCount(registers)) + addr_byte_size;
4098
4101 std::optional<RegisterInfo> dwarf_reg =
4103 context.SetRegisterPlusOffset(*dwarf_reg, offset);
4104
4105 // for i = 0 to 14
4106 for (int i = 0; i < 14; ++i) {
4107 // if registers<i> == '1' then
4108 if (BitIsSet(registers, i)) {
4109 // R[i] = MemA[address,4]; address = address + 4;
4110 context.SetRegisterPlusOffset(*dwarf_reg, Rn - (address + offset));
4111 uint32_t data =
4112 MemARead(context, address + offset, addr_byte_size, 0, &success);
4113 if (!success)
4114 return false;
4116 data))
4117 return false;
4118 offset += addr_byte_size;
4119 }
4120 }
4121
4122 // if registers<15> == '1' then
4123 // LoadWritePC(MemA[address,4]);
4124 if (BitIsSet(registers, 15)) {
4125 context.SetRegisterPlusOffset(*dwarf_reg, offset);
4126 uint32_t data =
4127 MemARead(context, address + offset, addr_byte_size, 0, &success);
4128 if (!success)
4129 return false;
4130 // In ARMv5T and above, this is an interworking branch.
4131 if (!LoadWritePC(context, data))
4132 return false;
4133 }
4134
4135 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4136 if (wback && BitIsClear(registers, n)) {
4137
4138 offset = (addr_byte_size * BitCount(registers)) * -1;
4140 context.SetImmediateSigned(offset);
4141 addr_t addr = Rn + offset;
4143 addr))
4144 return false;
4145 }
4146
4147 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4148 if (wback && BitIsSet(registers, n))
4149 return WriteBits32Unknown(n);
4150 }
4151 return true;
4152}
4153
4154// LDMDB loads multiple registers from consecutive memory locations using an
4155// address from a base register. The
4156// consecutive memory locations end just below this address, and the address of
4157// the lowest of those locations can be optionally written back to the base
4158// register.
4159bool EmulateInstructionARM::EmulateLDMDB(const uint32_t opcode,
4160 const ARMEncoding encoding) {
4161#if 0
4162 // ARM pseudo code...
4163 if ConditionPassed() then
4164 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4165 address = R[n] - 4*BitCount(registers);
4166
4167 for i = 0 to 14
4168 if registers<i> == '1' then
4169 R[i] = MemA[address,4]; address = address + 4;
4170 if registers<15> == '1' then
4171 LoadWritePC(MemA[address,4]);
4172
4173 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4174 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
4175#endif
4176
4177 bool success = false;
4178
4179 if (ConditionPassed(opcode)) {
4180 uint32_t n;
4181 uint32_t registers = 0;
4182 bool wback;
4183 const uint32_t addr_byte_size = GetAddressByteSize();
4184 switch (encoding) {
4185 case eEncodingT1:
4186 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
4187 n = Bits32(opcode, 19, 16);
4188 registers = Bits32(opcode, 15, 0);
4189 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
4190 wback = BitIsSet(opcode, 21);
4191
4192 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then
4193 // UNPREDICTABLE;
4194 if ((n == 15) || (BitCount(registers) < 2) ||
4195 (BitIsSet(opcode, 14) && BitIsSet(opcode, 15)))
4196 return false;
4197
4198 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
4199 // UNPREDICTABLE;
4200 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
4201 return false;
4202
4203 // if wback && registers<n> == '1' then UNPREDICTABLE;
4204 if (wback && BitIsSet(registers, n))
4205 return false;
4206
4207 break;
4208
4209 case eEncodingA1:
4210 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4211 n = Bits32(opcode, 19, 16);
4212 registers = Bits32(opcode, 15, 0);
4213 wback = BitIsSet(opcode, 21);
4214
4215 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4216 if ((n == 15) || (BitCount(registers) < 1))
4217 return false;
4218
4219 break;
4220
4221 default:
4222 return false;
4223 }
4224
4225 // address = R[n] - 4*BitCount(registers);
4226
4227 int32_t offset = 0;
4228 addr_t Rn =
4230
4231 if (!success)
4232 return false;
4233
4234 addr_t address = Rn - (addr_byte_size * BitCount(registers));
4237 std::optional<RegisterInfo> dwarf_reg =
4239 context.SetRegisterPlusOffset(*dwarf_reg, Rn - address);
4240
4241 for (int i = 0; i < 14; ++i) {
4242 if (BitIsSet(registers, i)) {
4243 // R[i] = MemA[address,4]; address = address + 4;
4244 context.SetRegisterPlusOffset(*dwarf_reg, Rn - (address + offset));
4245 uint32_t data =
4246 MemARead(context, address + offset, addr_byte_size, 0, &success);
4247 if (!success)
4248 return false;
4249
4251 data))
4252 return false;
4253
4254 offset += addr_byte_size;
4255 }
4256 }
4257
4258 // if registers<15> == '1' then
4259 // LoadWritePC(MemA[address,4]);
4260 if (BitIsSet(registers, 15)) {
4261 context.SetRegisterPlusOffset(*dwarf_reg, offset);
4262 uint32_t data =
4263 MemARead(context, address + offset, addr_byte_size, 0, &success);
4264 if (!success)
4265 return false;
4266 // In ARMv5T and above, this is an interworking branch.
4267 if (!LoadWritePC(context, data))
4268 return false;
4269 }
4270
4271 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4272 if (wback && BitIsClear(registers, n)) {
4273
4274 offset = (addr_byte_size * BitCount(registers)) * -1;
4276 context.SetImmediateSigned(offset);
4277 addr_t addr = Rn + offset;
4279 addr))
4280 return false;
4281 }
4282
4283 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only
4284 // possible for encoding A1
4285 if (wback && BitIsSet(registers, n))
4286 return WriteBits32Unknown(n);
4287 }
4288 return true;
4289}
4290
4291// LDMIB loads multiple registers from consecutive memory locations using an
4292// address from a base register. The
4293// consecutive memory locations start just above this address, and thea ddress
4294// of the last of those locations can optinoally be written back to the base
4295// register.
4296bool EmulateInstructionARM::EmulateLDMIB(const uint32_t opcode,
4297 const ARMEncoding encoding) {
4298#if 0
4299 if ConditionPassed() then
4300 EncodingSpecificOperations();
4301 address = R[n] + 4;
4302
4303 for i = 0 to 14
4304 if registers<i> == '1' then
4305 R[i] = MemA[address,4]; address = address + 4;
4306 if registers<15> == '1' then
4307 LoadWritePC(MemA[address,4]);
4308
4309 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
4310 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4311#endif
4312
4313 bool success = false;
4314
4315 if (ConditionPassed(opcode)) {
4316 uint32_t n;
4317 uint32_t registers = 0;
4318 bool wback;
4319 const uint32_t addr_byte_size = GetAddressByteSize();
4320 switch (encoding) {
4321 case eEncodingA1:
4322 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4323 n = Bits32(opcode, 19, 16);
4324 registers = Bits32(opcode, 15, 0);
4325 wback = BitIsSet(opcode, 21);
4326
4327 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4328 if ((n == 15) || (BitCount(registers) < 1))
4329 return false;
4330
4331 break;
4332 default:
4333 return false;
4334 }
4335 // address = R[n] + 4;
4336
4337 int32_t offset = 0;
4338 addr_t Rn =
4340
4341 if (!success)
4342 return false;
4343
4344 addr_t address = Rn + addr_byte_size;
4345
4348 std::optional<RegisterInfo> dwarf_reg =
4350 context.SetRegisterPlusOffset(*dwarf_reg, offset);
4351
4352 for (int i = 0; i < 14; ++i) {
4353 if (BitIsSet(registers, i)) {
4354 // R[i] = MemA[address,4]; address = address + 4;
4355
4356 context.SetRegisterPlusOffset(*dwarf_reg, offset + addr_byte_size);
4357 uint32_t data =
4358 MemARead(context, address + offset, addr_byte_size, 0, &success);
4359 if (!success)
4360 return false;
4361
4363 data))
4364 return false;
4365
4366 offset += addr_byte_size;
4367 }
4368 }
4369
4370 // if registers<15> == '1' then
4371 // LoadWritePC(MemA[address,4]);
4372 if (BitIsSet(registers, 15)) {
4373 context.SetRegisterPlusOffset(*dwarf_reg, offset);
4374 uint32_t data =
4375 MemARead(context, address + offset, addr_byte_size, 0, &success);
4376 if (!success)
4377 return false;
4378 // In ARMv5T and above, this is an interworking branch.
4379 if (!LoadWritePC(context, data))
4380 return false;
4381 }
4382
4383 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
4384 if (wback && BitIsClear(registers, n)) {
4385
4386 offset = addr_byte_size * BitCount(registers);
4388 context.SetImmediateSigned(offset);
4389 addr_t addr = Rn + offset;
4391 addr))
4392 return false;
4393 }
4394
4395 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only
4396 // possible for encoding A1
4397 if (wback && BitIsSet(registers, n))
4398 return WriteBits32Unknown(n);
4399 }
4400 return true;
4401}
4402
4403// Load Register (immediate) calculates an address from a base register value
4404// and an immediate offset, loads a word from memory, and writes to a register.
4405// LDR (immediate, Thumb)
4407 const ARMEncoding encoding) {
4408#if 0
4409 // ARM pseudo code...
4410 if (ConditionPassed())
4411 {
4412 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
4413 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4414 address = if index then offset_addr else R[n];
4415 data = MemU[address,4];
4416 if wback then R[n] = offset_addr;
4417 if t == 15 then
4418 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
4419 elsif UnalignedSupport() || address<1:0> = '00' then
4420 R[t] = data;
4421 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
4422 }
4423#endif
4424
4425 bool success = false;
4426
4427 if (ConditionPassed(opcode)) {
4428 uint32_t Rt; // the destination register
4429 uint32_t Rn; // the base register
4430 uint32_t imm32; // the immediate offset used to form the address
4431 addr_t offset_addr; // the offset address
4432 addr_t address; // the calculated address
4433 uint32_t data; // the literal data value from memory load
4434 bool add, index, wback;
4435 switch (encoding) {
4436 case eEncodingT1:
4437 Rt = Bits32(opcode, 2, 0);
4438 Rn = Bits32(opcode, 5, 3);
4439 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
4440 // index = TRUE; add = TRUE; wback = FALSE
4441 add = true;
4442 index = true;
4443 wback = false;
4444
4445 break;
4446
4447 case eEncodingT2:
4448 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
4449 Rt = Bits32(opcode, 10, 8);
4450 Rn = 13;
4451 imm32 = Bits32(opcode, 7, 0) << 2;
4452
4453 // index = TRUE; add = TRUE; wback = FALSE;
4454 index = true;
4455 add = true;
4456 wback = false;
4457
4458 break;
4459
4460 case eEncodingT3:
4461 // if Rn == '1111' then SEE LDR (literal);
4462 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4463 Rt = Bits32(opcode, 15, 12);
4464 Rn = Bits32(opcode, 19, 16);
4465 imm32 = Bits32(opcode, 11, 0);
4466
4467 // index = TRUE; add = TRUE; wback = FALSE;
4468 index = true;
4469 add = true;
4470 wback = false;
4471
4472 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
4473 if ((Rt == 15) && InITBlock() && !LastInITBlock())
4474 return false;
4475
4476 break;
4477
4478 case eEncodingT4:
4479 // if Rn == '1111' then SEE LDR (literal);
4480 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
4481 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 ==
4482 // '00000100' then SEE POP;
4483 // if P == '0' && W == '0' then UNDEFINED;
4484 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
4485 return false;
4486
4487 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4488 Rt = Bits32(opcode, 15, 12);
4489 Rn = Bits32(opcode, 19, 16);
4490 imm32 = Bits32(opcode, 7, 0);
4491
4492 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
4493 index = BitIsSet(opcode, 10);
4494 add = BitIsSet(opcode, 9);
4495 wback = BitIsSet(opcode, 8);
4496
4497 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock())
4498 // then UNPREDICTABLE;
4499 if ((wback && (Rn == Rt)) ||
4500 ((Rt == 15) && InITBlock() && !LastInITBlock()))
4501 return false;
4502
4503 break;
4504
4505 default:
4506 return false;
4507 }
4508 uint32_t base = ReadCoreReg(Rn, &success);
4509 if (!success)
4510 return false;
4511 if (add)
4512 offset_addr = base + imm32;
4513 else
4514 offset_addr = base - imm32;
4515
4516 address = (index ? offset_addr : base);
4517
4518 std::optional<RegisterInfo> base_reg =
4520 if (wback) {
4522 if (Rn == 13) {
4524 ctx.SetImmediateSigned((int32_t)(offset_addr - base));
4525 } else if (Rn == GetFramePointerRegisterNumber()) {
4527 ctx.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base));
4528 } else {
4530 ctx.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base));
4531 }
4532
4534 offset_addr))
4535 return false;
4536 }
4537
4538 // Prepare to write to the Rt register.
4541 context.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base));
4542
4543 // Read memory from the address.
4544 data = MemURead(context, address, 4, 0, &success);
4545 if (!success)
4546 return false;
4547
4548 if (Rt == 15) {
4549 if (Bits32(address, 1, 0) == 0) {
4550 if (!LoadWritePC(context, data))
4551 return false;
4552 } else
4553 return false;
4554 } else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) {
4556 data))
4557 return false;
4558 } else
4560 }
4561 return true;
4562}
4563
4564// STM (Store Multiple Increment After) stores multiple registers to consecutive
4565// memory locations using an address
4566// from a base register. The consecutive memory locations start at this
4567// address, and the address just above the last of those locations can
4568// optionally be written back to the base register.
4569bool EmulateInstructionARM::EmulateSTM(const uint32_t opcode,
4570 const ARMEncoding encoding) {
4571#if 0
4572 if ConditionPassed() then
4573 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4574 address = R[n];
4575
4576 for i = 0 to 14
4577 if registers<i> == '1' then
4578 if i == n && wback && i != LowestSetBit(registers) then
4579 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
4580 else
4581 MemA[address,4] = R[i];
4582 address = address + 4;
4583
4584 if registers<15> == '1' then // Only possible for encoding A1
4585 MemA[address,4] = PCStoreValue();
4586 if wback then R[n] = R[n] + 4*BitCount(registers);
4587#endif
4588
4589 bool success = false;
4590
4591 if (ConditionPassed(opcode)) {
4592 uint32_t n;
4593 uint32_t registers = 0;
4594 bool wback;
4595 const uint32_t addr_byte_size = GetAddressByteSize();
4596
4597 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4598 switch (encoding) {
4599 case eEncodingT1:
4600 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
4601 n = Bits32(opcode, 10, 8);
4602 registers = Bits32(opcode, 7, 0);
4603 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
4604 wback = true;
4605
4606 // if BitCount(registers) < 1 then UNPREDICTABLE;
4607 if (BitCount(registers) < 1)
4608 return false;
4609
4610 break;
4611
4612 case eEncodingT2:
4613 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4614 n = Bits32(opcode, 19, 16);
4615 registers = Bits32(opcode, 15, 0);
4616 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4617 wback = BitIsSet(opcode, 21);
4618
4619 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4620 if ((n == 15) || (BitCount(registers) < 2))
4621 return false;
4622
4623 // if wback && registers<n> == '1' then UNPREDICTABLE;
4624 if (wback && BitIsSet(registers, n))
4625 return false;
4626
4627 break;
4628
4629 case eEncodingA1:
4630 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4631 n = Bits32(opcode, 19, 16);
4632 registers = Bits32(opcode, 15, 0);
4633 wback = BitIsSet(opcode, 21);
4634
4635 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4636 if ((n == 15) || (BitCount(registers) < 1))
4637 return false;
4638
4639 break;
4640
4641 default:
4642 return false;
4643 }
4644
4645 // address = R[n];
4646 int32_t offset = 0;
4647 const addr_t address =
4649 if (!success)
4650 return false;
4651
4654 std::optional<RegisterInfo> base_reg =
4656
4657 // for i = 0 to 14
4658 uint32_t lowest_set_bit = 14;
4659 for (uint32_t i = 0; i < 14; ++i) {
4660 // if registers<i> == '1' then
4661 if (BitIsSet(registers, i)) {
4662 if (i < lowest_set_bit)
4663 lowest_set_bit = i;
4664 // if i == n && wback && i != LowestSetBit(registers) then
4665 if ((i == n) && wback && (i != lowest_set_bit))
4666 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings
4667 // T1 and A1
4668 WriteBits32UnknownToMemory(address + offset);
4669 else {
4670 // MemA[address,4] = R[i];
4672 0, &success);
4673 if (!success)
4674 return false;
4675
4676 std::optional<RegisterInfo> data_reg =
4678 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, offset);
4679 if (!MemAWrite(context, address + offset, data, addr_byte_size))
4680 return false;
4681 }
4682
4683 // address = address + 4;
4684 offset += addr_byte_size;
4685 }
4686 }
4687
4688 // if registers<15> == '1' then // Only possible for encoding A1
4689 // MemA[address,4] = PCStoreValue();
4690 if (BitIsSet(registers, 15)) {
4691 std::optional<RegisterInfo> pc_reg =
4693 context.SetRegisterPlusOffset(*pc_reg, 8);
4694 const uint32_t pc = ReadCoreReg(PC_REG, &success);
4695 if (!success)
4696 return false;
4697
4698 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4699 return false;
4700 }
4701
4702 // if wback then R[n] = R[n] + 4*BitCount(registers);
4703 if (wback) {
4704 offset = addr_byte_size * BitCount(registers);
4706 context.SetImmediateSigned(offset);
4707 addr_t data = address + offset;
4709 data))
4710 return false;
4711 }
4712 }
4713 return true;
4714}
4715
4716// STMDA (Store Multiple Decrement After) stores multiple registers to
4717// consecutive memory locations using an address from a base register. The
4718// consecutive memory locations end at this address, and the address just below
4719// the lowest of those locations can optionally be written back to the base
4720// register.
4721bool EmulateInstructionARM::EmulateSTMDA(const uint32_t opcode,
4722 const ARMEncoding encoding) {
4723#if 0
4724 if ConditionPassed() then
4725 EncodingSpecificOperations();
4726 address = R[n] - 4*BitCount(registers) + 4;
4727
4728 for i = 0 to 14
4729 if registers<i> == '1' then
4730 if i == n && wback && i != LowestSetBit(registers) then
4731 MemA[address,4] = bits(32) UNKNOWN;
4732 else
4733 MemA[address,4] = R[i];
4734 address = address + 4;
4735
4736 if registers<15> == '1' then
4737 MemA[address,4] = PCStoreValue();
4738
4739 if wback then R[n] = R[n] - 4*BitCount(registers);
4740#endif
4741
4742 bool success = false;
4743
4744 if (ConditionPassed(opcode)) {
4745 uint32_t n;
4746 uint32_t registers = 0;
4747 bool wback;
4748 const uint32_t addr_byte_size = GetAddressByteSize();
4749
4750 // EncodingSpecificOperations();
4751 switch (encoding) {
4752 case eEncodingA1:
4753 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4754 n = Bits32(opcode, 19, 16);
4755 registers = Bits32(opcode, 15, 0);
4756 wback = BitIsSet(opcode, 21);
4757
4758 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4759 if ((n == 15) || (BitCount(registers) < 1))
4760 return false;
4761 break;
4762 default:
4763 return false;
4764 }
4765
4766 // address = R[n] - 4*BitCount(registers) + 4;
4767 int32_t offset = 0;
4768 addr_t Rn = ReadCoreReg(n, &success);
4769 if (!success)
4770 return false;
4771
4772 addr_t address = Rn - (addr_byte_size * BitCount(registers)) + 4;
4773
4776 std::optional<RegisterInfo> base_reg =
4778
4779 // for i = 0 to 14
4780 uint32_t lowest_bit_set = 14;
4781 for (uint32_t i = 0; i < 14; ++i) {
4782 // if registers<i> == '1' then
4783 if (BitIsSet(registers, i)) {
4784 if (i < lowest_bit_set)
4785 lowest_bit_set = i;
4786 // if i == n && wback && i != LowestSetBit(registers) then
4787 if ((i == n) && wback && (i != lowest_bit_set))
4788 // MemA[address,4] = bits(32) UNKNOWN;
4789 WriteBits32UnknownToMemory(address + offset);
4790 else {
4791 // MemA[address,4] = R[i];
4793 0, &success);
4794 if (!success)
4795 return false;
4796
4797 std::optional<RegisterInfo> data_reg =
4799 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
4800 Rn - (address + offset));
4801 if (!MemAWrite(context, address + offset, data, addr_byte_size))
4802 return false;
4803 }
4804
4805 // address = address + 4;
4806 offset += addr_byte_size;
4807 }
4808 }
4809
4810 // if registers<15> == '1' then
4811 // MemA[address,4] = PCStoreValue();
4812 if (BitIsSet(registers, 15)) {
4813 std::optional<RegisterInfo> pc_reg =
4815 context.SetRegisterPlusOffset(*pc_reg, 8);
4816 const uint32_t pc = ReadCoreReg(PC_REG, &success);
4817 if (!success)
4818 return false;
4819
4820 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4821 return false;
4822 }
4823
4824 // if wback then R[n] = R[n] - 4*BitCount(registers);
4825 if (wback) {
4826 offset = (addr_byte_size * BitCount(registers)) * -1;
4828 context.SetImmediateSigned(offset);
4829 addr_t data = Rn + offset;
4831 data))
4832 return false;
4833 }
4834 }
4835 return true;
4836}
4837
4838// STMDB (Store Multiple Decrement Before) stores multiple registers to
4839// consecutive memory locations using an address from a base register. The
4840// consecutive memory locations end just below this address, and the address of
4841// the first of those locations can optionally be written back to the base
4842// register.
4843bool EmulateInstructionARM::EmulateSTMDB(const uint32_t opcode,
4844 const ARMEncoding encoding) {
4845#if 0
4846 if ConditionPassed() then
4847 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4848 address = R[n] - 4*BitCount(registers);
4849
4850 for i = 0 to 14
4851 if registers<i> == '1' then
4852 if i == n && wback && i != LowestSetBit(registers) then
4853 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4854 else
4855 MemA[address,4] = R[i];
4856 address = address + 4;
4857
4858 if registers<15> == '1' then // Only possible for encoding A1
4859 MemA[address,4] = PCStoreValue();
4860
4861 if wback then R[n] = R[n] - 4*BitCount(registers);
4862#endif
4863
4864 bool success = false;
4865
4866 if (ConditionPassed(opcode)) {
4867 uint32_t n;
4868 uint32_t registers = 0;
4869 bool wback;
4870 const uint32_t addr_byte_size = GetAddressByteSize();
4871
4872 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4873 switch (encoding) {
4874 case eEncodingT1:
4875 // if W == '1' && Rn == '1101' then SEE PUSH;
4876 if ((BitIsSet(opcode, 21)) && (Bits32(opcode, 19, 16) == 13)) {
4877 // See PUSH
4878 }
4879 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4880 n = Bits32(opcode, 19, 16);
4881 registers = Bits32(opcode, 15, 0);
4882 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4883 wback = BitIsSet(opcode, 21);
4884 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4885 if ((n == 15) || BitCount(registers) < 2)
4886 return false;
4887 // if wback && registers<n> == '1' then UNPREDICTABLE;
4888 if (wback && BitIsSet(registers, n))
4889 return false;
4890 break;
4891
4892 case eEncodingA1:
4893 // if W == '1' && Rn == '1101' && BitCount(register_list) >= 2 then SEE
4894 // PUSH;
4895 if (BitIsSet(opcode, 21) && (Bits32(opcode, 19, 16) == 13) &&
4896 BitCount(Bits32(opcode, 15, 0)) >= 2) {
4897 // See Push
4898 }
4899 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4900 n = Bits32(opcode, 19, 16);
4901 registers = Bits32(opcode, 15, 0);
4902 wback = BitIsSet(opcode, 21);
4903 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4904 if ((n == 15) || BitCount(registers) < 1)
4905 return false;
4906 break;
4907
4908 default:
4909 return false;
4910 }
4911
4912 // address = R[n] - 4*BitCount(registers);
4913
4914 int32_t offset = 0;
4915 addr_t Rn =
4917 if (!success)
4918 return false;
4919
4920 addr_t address = Rn - (addr_byte_size * BitCount(registers));
4921
4924 std::optional<RegisterInfo> base_reg =
4926
4927 // for i = 0 to 14
4928 uint32_t lowest_set_bit = 14;
4929 for (uint32_t i = 0; i < 14; ++i) {
4930 // if registers<i> == '1' then
4931 if (BitIsSet(registers, i)) {
4932 if (i < lowest_set_bit)
4933 lowest_set_bit = i;
4934 // if i == n && wback && i != LowestSetBit(registers) then
4935 if ((i == n) && wback && (i != lowest_set_bit))
4936 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding
4937 // A1
4938 WriteBits32UnknownToMemory(address + offset);
4939 else {
4940 // MemA[address,4] = R[i];
4942 0, &success);
4943 if (!success)
4944 return false;
4945
4946 std::optional<RegisterInfo> data_reg =
4948 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
4949 Rn - (address + offset));
4950 if (!MemAWrite(context, address + offset, data, addr_byte_size))
4951 return false;
4952 }
4953
4954 // address = address + 4;
4955 offset += addr_byte_size;
4956 }
4957 }
4958
4959 // if registers<15> == '1' then // Only possible for encoding A1
4960 // MemA[address,4] = PCStoreValue();
4961 if (BitIsSet(registers, 15)) {
4962 std::optional<RegisterInfo> pc_reg =
4964 context.SetRegisterPlusOffset(*pc_reg, 8);
4965 const uint32_t pc = ReadCoreReg(PC_REG, &success);
4966 if (!success)
4967 return false;
4968
4969 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4970 return false;
4971 }
4972
4973 // if wback then R[n] = R[n] - 4*BitCount(registers);
4974 if (wback) {
4975 offset = (addr_byte_size * BitCount(registers)) * -1;
4977 context.SetImmediateSigned(offset);
4978 addr_t data = Rn + offset;
4980 data))
4981 return false;
4982 }
4983 }
4984 return true;
4985}
4986
4987// STMIB (Store Multiple Increment Before) stores multiple registers to
4988// consecutive memory locations using an address from a base register. The
4989// consecutive memory locations start just above this address, and the address
4990// of the last of those locations can optionally be written back to the base
4991// register.
4992bool EmulateInstructionARM::EmulateSTMIB(const uint32_t opcode,
4993 const ARMEncoding encoding) {
4994#if 0
4995 if ConditionPassed() then
4996 EncodingSpecificOperations();
4997 address = R[n] + 4;
4998
4999 for i = 0 to 14
5000 if registers<i> == '1' then
5001 if i == n && wback && i != LowestSetBit(registers) then
5002 MemA[address,4] = bits(32) UNKNOWN;
5003 else
5004 MemA[address,4] = R[i];
5005 address = address + 4;
5006
5007 if registers<15> == '1' then
5008 MemA[address,4] = PCStoreValue();
5009
5010 if wback then R[n] = R[n] + 4*BitCount(registers);
5011#endif
5012
5013 bool success = false;
5014
5015 if (ConditionPassed(opcode)) {
5016 uint32_t n;
5017 uint32_t registers = 0;
5018 bool wback;
5019 const uint32_t addr_byte_size = GetAddressByteSize();
5020
5021 // EncodingSpecificOperations();
5022 switch (encoding) {
5023 case eEncodingA1:
5024 // n = UInt(Rn); registers = register_list; wback = (W == '1');
5025 n = Bits32(opcode, 19, 16);
5026 registers = Bits32(opcode, 15, 0);
5027 wback = BitIsSet(opcode, 21);
5028
5029 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
5030 if ((n == 15) && (BitCount(registers) < 1))
5031 return false;
5032 break;
5033 default:
5034 return false;
5035 }
5036 // address = R[n] + 4;
5037
5038 int32_t offset = 0;
5039 addr_t Rn = ReadCoreReg(n, &success);
5040 if (!success)
5041 return false;
5042
5043 addr_t address = Rn + addr_byte_size;
5044
5047 std::optional<RegisterInfo> base_reg =
5049
5050 uint32_t lowest_set_bit = 14;
5051 // for i = 0 to 14
5052 for (uint32_t i = 0; i < 14; ++i) {
5053 // if registers<i> == '1' then
5054 if (BitIsSet(registers, i)) {
5055 if (i < lowest_set_bit)
5056 lowest_set_bit = i;
5057 // if i == n && wback && i != LowestSetBit(registers) then
5058 if ((i == n) && wback && (i != lowest_set_bit))
5059 // MemA[address,4] = bits(32) UNKNOWN;
5060 WriteBits32UnknownToMemory(address + offset);
5061 // else
5062 else {
5063 // MemA[address,4] = R[i];
5065 0, &success);
5066 if (!success)
5067 return false;
5068
5069 std::optional<RegisterInfo> data_reg =
5071 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
5072 offset + addr_byte_size);
5073 if (!MemAWrite(context, address + offset, data, addr_byte_size))
5074 return false;
5075 }
5076
5077 // address = address + 4;
5078 offset += addr_byte_size;
5079 }
5080 }
5081
5082 // if registers<15> == '1' then
5083 // MemA[address,4] = PCStoreValue();
5084 if (BitIsSet(registers, 15)) {
5085 std::optional<RegisterInfo> pc_reg =
5087 context.SetRegisterPlusOffset(*pc_reg, 8);
5088 const uint32_t pc = ReadCoreReg(PC_REG, &success);
5089 if (!success)
5090 return false;
5091
5092 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
5093 return false;
5094 }
5095
5096 // if wback then R[n] = R[n] + 4*BitCount(registers);
5097 if (wback) {
5098 offset = addr_byte_size * BitCount(registers);
5100 context.SetImmediateSigned(offset);
5101 addr_t data = Rn + offset;
5103 data))
5104 return false;
5105 }
5106 }
5107 return true;
5108}
5109
5110// STR (store immediate) calculates an address from a base register value and an
5111// immediate offset, and stores a word
5112// from a register to memory. It can use offset, post-indexed, or pre-indexed
5113// addressing.
5115 const ARMEncoding encoding) {
5116#if 0
5117 if ConditionPassed() then
5118 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5119 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);