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
11 #include "EmulateInstructionARM.h"
12 #include "EmulationStateARM.h"
13 #include "lldb/Core/Address.h"
14 #include "lldb/Core/PluginManager.h"
15 #include "lldb/Host/PosixApi.h"
16 #include "lldb/Interpreter/OptionValueArray.h"
17 #include "lldb/Interpreter/OptionValueDictionary.h"
18 #include "lldb/Symbol/UnwindPlan.h"
19 #include "lldb/Utility/ArchSpec.h"
20 #include "lldb/Utility/ConstString.h"
21 #include "lldb/Utility/Stream.h"
22
23 #include "Plugins/Process/Utility/ARMDefines.h"
24 #include "Plugins/Process/Utility/ARMUtils.h"
25 #include "Utility/ARM_DWARF_Registers.h"
26
27 #include "llvm/ADT/STLExtras.h"
28 #include "llvm/Support/MathExtras.h"
29
30 using namespace lldb;
31 using namespace lldb_private;
32
LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionARM,InstructionARM)33 LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionARM, InstructionARM)
34
35 // Convenient macro definitions.
36 #define APSR_C Bit32(m_opcode_cpsr, CPSR_C_POS)
37 #define APSR_V Bit32(m_opcode_cpsr, CPSR_V_POS)
38
39 #define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
40
41 //
42 // ITSession implementation
43 //
44
45 static bool GetARMDWARFRegisterInfo(unsigned reg_num, RegisterInfo ®_info) {
46 ::memset(®_info, 0, sizeof(RegisterInfo));
47 ::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
48
49 if (reg_num >= dwarf_q0 && reg_num <= dwarf_q15) {
50 reg_info.byte_size = 16;
51 reg_info.format = eFormatVectorOfUInt8;
52 reg_info.encoding = eEncodingVector;
53 }
54
55 if (reg_num >= dwarf_d0 && reg_num <= dwarf_d31) {
56 reg_info.byte_size = 8;
57 reg_info.format = eFormatFloat;
58 reg_info.encoding = eEncodingIEEE754;
59 } else if (reg_num >= dwarf_s0 && reg_num <= dwarf_s31) {
60 reg_info.byte_size = 4;
61 reg_info.format = eFormatFloat;
62 reg_info.encoding = eEncodingIEEE754;
63 } else if (reg_num >= dwarf_f0 && reg_num <= dwarf_f7) {
64 reg_info.byte_size = 12;
65 reg_info.format = eFormatFloat;
66 reg_info.encoding = eEncodingIEEE754;
67 } else {
68 reg_info.byte_size = 4;
69 reg_info.format = eFormatHex;
70 reg_info.encoding = eEncodingUint;
71 }
72
73 reg_info.kinds[eRegisterKindDWARF] = reg_num;
74
75 switch (reg_num) {
76 case dwarf_r0:
77 reg_info.name = "r0";
78 break;
79 case dwarf_r1:
80 reg_info.name = "r1";
81 break;
82 case dwarf_r2:
83 reg_info.name = "r2";
84 break;
85 case dwarf_r3:
86 reg_info.name = "r3";
87 break;
88 case dwarf_r4:
89 reg_info.name = "r4";
90 break;
91 case dwarf_r5:
92 reg_info.name = "r5";
93 break;
94 case dwarf_r6:
95 reg_info.name = "r6";
96 break;
97 case dwarf_r7:
98 reg_info.name = "r7";
99 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
100 break;
101 case dwarf_r8:
102 reg_info.name = "r8";
103 break;
104 case dwarf_r9:
105 reg_info.name = "r9";
106 break;
107 case dwarf_r10:
108 reg_info.name = "r10";
109 break;
110 case dwarf_r11:
111 reg_info.name = "r11";
112 break;
113 case dwarf_r12:
114 reg_info.name = "r12";
115 break;
116 case dwarf_sp:
117 reg_info.name = "sp";
118 reg_info.alt_name = "r13";
119 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
120 break;
121 case dwarf_lr:
122 reg_info.name = "lr";
123 reg_info.alt_name = "r14";
124 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;
125 break;
126 case dwarf_pc:
127 reg_info.name = "pc";
128 reg_info.alt_name = "r15";
129 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
130 break;
131 case dwarf_cpsr:
132 reg_info.name = "cpsr";
133 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
134 break;
135
136 case dwarf_s0:
137 reg_info.name = "s0";
138 break;
139 case dwarf_s1:
140 reg_info.name = "s1";
141 break;
142 case dwarf_s2:
143 reg_info.name = "s2";
144 break;
145 case dwarf_s3:
146 reg_info.name = "s3";
147 break;
148 case dwarf_s4:
149 reg_info.name = "s4";
150 break;
151 case dwarf_s5:
152 reg_info.name = "s5";
153 break;
154 case dwarf_s6:
155 reg_info.name = "s6";
156 break;
157 case dwarf_s7:
158 reg_info.name = "s7";
159 break;
160 case dwarf_s8:
161 reg_info.name = "s8";
162 break;
163 case dwarf_s9:
164 reg_info.name = "s9";
165 break;
166 case dwarf_s10:
167 reg_info.name = "s10";
168 break;
169 case dwarf_s11:
170 reg_info.name = "s11";
171 break;
172 case dwarf_s12:
173 reg_info.name = "s12";
174 break;
175 case dwarf_s13:
176 reg_info.name = "s13";
177 break;
178 case dwarf_s14:
179 reg_info.name = "s14";
180 break;
181 case dwarf_s15:
182 reg_info.name = "s15";
183 break;
184 case dwarf_s16:
185 reg_info.name = "s16";
186 break;
187 case dwarf_s17:
188 reg_info.name = "s17";
189 break;
190 case dwarf_s18:
191 reg_info.name = "s18";
192 break;
193 case dwarf_s19:
194 reg_info.name = "s19";
195 break;
196 case dwarf_s20:
197 reg_info.name = "s20";
198 break;
199 case dwarf_s21:
200 reg_info.name = "s21";
201 break;
202 case dwarf_s22:
203 reg_info.name = "s22";
204 break;
205 case dwarf_s23:
206 reg_info.name = "s23";
207 break;
208 case dwarf_s24:
209 reg_info.name = "s24";
210 break;
211 case dwarf_s25:
212 reg_info.name = "s25";
213 break;
214 case dwarf_s26:
215 reg_info.name = "s26";
216 break;
217 case dwarf_s27:
218 reg_info.name = "s27";
219 break;
220 case dwarf_s28:
221 reg_info.name = "s28";
222 break;
223 case dwarf_s29:
224 reg_info.name = "s29";
225 break;
226 case dwarf_s30:
227 reg_info.name = "s30";
228 break;
229 case dwarf_s31:
230 reg_info.name = "s31";
231 break;
232
233 // FPA Registers 0-7
234 case dwarf_f0:
235 reg_info.name = "f0";
236 break;
237 case dwarf_f1:
238 reg_info.name = "f1";
239 break;
240 case dwarf_f2:
241 reg_info.name = "f2";
242 break;
243 case dwarf_f3:
244 reg_info.name = "f3";
245 break;
246 case dwarf_f4:
247 reg_info.name = "f4";
248 break;
249 case dwarf_f5:
250 reg_info.name = "f5";
251 break;
252 case dwarf_f6:
253 reg_info.name = "f6";
254 break;
255 case dwarf_f7:
256 reg_info.name = "f7";
257 break;
258
259 // Intel wireless MMX general purpose registers 0 - 7 XScale accumulator
260 // register 0 - 7 (they do overlap with wCGR0 - wCGR7)
261 case dwarf_wCGR0:
262 reg_info.name = "wCGR0/ACC0";
263 break;
264 case dwarf_wCGR1:
265 reg_info.name = "wCGR1/ACC1";
266 break;
267 case dwarf_wCGR2:
268 reg_info.name = "wCGR2/ACC2";
269 break;
270 case dwarf_wCGR3:
271 reg_info.name = "wCGR3/ACC3";
272 break;
273 case dwarf_wCGR4:
274 reg_info.name = "wCGR4/ACC4";
275 break;
276 case dwarf_wCGR5:
277 reg_info.name = "wCGR5/ACC5";
278 break;
279 case dwarf_wCGR6:
280 reg_info.name = "wCGR6/ACC6";
281 break;
282 case dwarf_wCGR7:
283 reg_info.name = "wCGR7/ACC7";
284 break;
285
286 // Intel wireless MMX data registers 0 - 15
287 case dwarf_wR0:
288 reg_info.name = "wR0";
289 break;
290 case dwarf_wR1:
291 reg_info.name = "wR1";
292 break;
293 case dwarf_wR2:
294 reg_info.name = "wR2";
295 break;
296 case dwarf_wR3:
297 reg_info.name = "wR3";
298 break;
299 case dwarf_wR4:
300 reg_info.name = "wR4";
301 break;
302 case dwarf_wR5:
303 reg_info.name = "wR5";
304 break;
305 case dwarf_wR6:
306 reg_info.name = "wR6";
307 break;
308 case dwarf_wR7:
309 reg_info.name = "wR7";
310 break;
311 case dwarf_wR8:
312 reg_info.name = "wR8";
313 break;
314 case dwarf_wR9:
315 reg_info.name = "wR9";
316 break;
317 case dwarf_wR10:
318 reg_info.name = "wR10";
319 break;
320 case dwarf_wR11:
321 reg_info.name = "wR11";
322 break;
323 case dwarf_wR12:
324 reg_info.name = "wR12";
325 break;
326 case dwarf_wR13:
327 reg_info.name = "wR13";
328 break;
329 case dwarf_wR14:
330 reg_info.name = "wR14";
331 break;
332 case dwarf_wR15:
333 reg_info.name = "wR15";
334 break;
335
336 case dwarf_spsr:
337 reg_info.name = "spsr";
338 break;
339 case dwarf_spsr_fiq:
340 reg_info.name = "spsr_fiq";
341 break;
342 case dwarf_spsr_irq:
343 reg_info.name = "spsr_irq";
344 break;
345 case dwarf_spsr_abt:
346 reg_info.name = "spsr_abt";
347 break;
348 case dwarf_spsr_und:
349 reg_info.name = "spsr_und";
350 break;
351 case dwarf_spsr_svc:
352 reg_info.name = "spsr_svc";
353 break;
354
355 case dwarf_r8_usr:
356 reg_info.name = "r8_usr";
357 break;
358 case dwarf_r9_usr:
359 reg_info.name = "r9_usr";
360 break;
361 case dwarf_r10_usr:
362 reg_info.name = "r10_usr";
363 break;
364 case dwarf_r11_usr:
365 reg_info.name = "r11_usr";
366 break;
367 case dwarf_r12_usr:
368 reg_info.name = "r12_usr";
369 break;
370 case dwarf_r13_usr:
371 reg_info.name = "r13_usr";
372 break;
373 case dwarf_r14_usr:
374 reg_info.name = "r14_usr";
375 break;
376 case dwarf_r8_fiq:
377 reg_info.name = "r8_fiq";
378 break;
379 case dwarf_r9_fiq:
380 reg_info.name = "r9_fiq";
381 break;
382 case dwarf_r10_fiq:
383 reg_info.name = "r10_fiq";
384 break;
385 case dwarf_r11_fiq:
386 reg_info.name = "r11_fiq";
387 break;
388 case dwarf_r12_fiq:
389 reg_info.name = "r12_fiq";
390 break;
391 case dwarf_r13_fiq:
392 reg_info.name = "r13_fiq";
393 break;
394 case dwarf_r14_fiq:
395 reg_info.name = "r14_fiq";
396 break;
397 case dwarf_r13_irq:
398 reg_info.name = "r13_irq";
399 break;
400 case dwarf_r14_irq:
401 reg_info.name = "r14_irq";
402 break;
403 case dwarf_r13_abt:
404 reg_info.name = "r13_abt";
405 break;
406 case dwarf_r14_abt:
407 reg_info.name = "r14_abt";
408 break;
409 case dwarf_r13_und:
410 reg_info.name = "r13_und";
411 break;
412 case dwarf_r14_und:
413 reg_info.name = "r14_und";
414 break;
415 case dwarf_r13_svc:
416 reg_info.name = "r13_svc";
417 break;
418 case dwarf_r14_svc:
419 reg_info.name = "r14_svc";
420 break;
421
422 // Intel wireless MMX control register in co-processor 0 - 7
423 case dwarf_wC0:
424 reg_info.name = "wC0";
425 break;
426 case dwarf_wC1:
427 reg_info.name = "wC1";
428 break;
429 case dwarf_wC2:
430 reg_info.name = "wC2";
431 break;
432 case dwarf_wC3:
433 reg_info.name = "wC3";
434 break;
435 case dwarf_wC4:
436 reg_info.name = "wC4";
437 break;
438 case dwarf_wC5:
439 reg_info.name = "wC5";
440 break;
441 case dwarf_wC6:
442 reg_info.name = "wC6";
443 break;
444 case dwarf_wC7:
445 reg_info.name = "wC7";
446 break;
447
448 // VFP-v3/Neon
449 case dwarf_d0:
450 reg_info.name = "d0";
451 break;
452 case dwarf_d1:
453 reg_info.name = "d1";
454 break;
455 case dwarf_d2:
456 reg_info.name = "d2";
457 break;
458 case dwarf_d3:
459 reg_info.name = "d3";
460 break;
461 case dwarf_d4:
462 reg_info.name = "d4";
463 break;
464 case dwarf_d5:
465 reg_info.name = "d5";
466 break;
467 case dwarf_d6:
468 reg_info.name = "d6";
469 break;
470 case dwarf_d7:
471 reg_info.name = "d7";
472 break;
473 case dwarf_d8:
474 reg_info.name = "d8";
475 break;
476 case dwarf_d9:
477 reg_info.name = "d9";
478 break;
479 case dwarf_d10:
480 reg_info.name = "d10";
481 break;
482 case dwarf_d11:
483 reg_info.name = "d11";
484 break;
485 case dwarf_d12:
486 reg_info.name = "d12";
487 break;
488 case dwarf_d13:
489 reg_info.name = "d13";
490 break;
491 case dwarf_d14:
492 reg_info.name = "d14";
493 break;
494 case dwarf_d15:
495 reg_info.name = "d15";
496 break;
497 case dwarf_d16:
498 reg_info.name = "d16";
499 break;
500 case dwarf_d17:
501 reg_info.name = "d17";
502 break;
503 case dwarf_d18:
504 reg_info.name = "d18";
505 break;
506 case dwarf_d19:
507 reg_info.name = "d19";
508 break;
509 case dwarf_d20:
510 reg_info.name = "d20";
511 break;
512 case dwarf_d21:
513 reg_info.name = "d21";
514 break;
515 case dwarf_d22:
516 reg_info.name = "d22";
517 break;
518 case dwarf_d23:
519 reg_info.name = "d23";
520 break;
521 case dwarf_d24:
522 reg_info.name = "d24";
523 break;
524 case dwarf_d25:
525 reg_info.name = "d25";
526 break;
527 case dwarf_d26:
528 reg_info.name = "d26";
529 break;
530 case dwarf_d27:
531 reg_info.name = "d27";
532 break;
533 case dwarf_d28:
534 reg_info.name = "d28";
535 break;
536 case dwarf_d29:
537 reg_info.name = "d29";
538 break;
539 case dwarf_d30:
540 reg_info.name = "d30";
541 break;
542 case dwarf_d31:
543 reg_info.name = "d31";
544 break;
545
546 // NEON 128-bit vector registers (overlays the d registers)
547 case dwarf_q0:
548 reg_info.name = "q0";
549 break;
550 case dwarf_q1:
551 reg_info.name = "q1";
552 break;
553 case dwarf_q2:
554 reg_info.name = "q2";
555 break;
556 case dwarf_q3:
557 reg_info.name = "q3";
558 break;
559 case dwarf_q4:
560 reg_info.name = "q4";
561 break;
562 case dwarf_q5:
563 reg_info.name = "q5";
564 break;
565 case dwarf_q6:
566 reg_info.name = "q6";
567 break;
568 case dwarf_q7:
569 reg_info.name = "q7";
570 break;
571 case dwarf_q8:
572 reg_info.name = "q8";
573 break;
574 case dwarf_q9:
575 reg_info.name = "q9";
576 break;
577 case dwarf_q10:
578 reg_info.name = "q10";
579 break;
580 case dwarf_q11:
581 reg_info.name = "q11";
582 break;
583 case dwarf_q12:
584 reg_info.name = "q12";
585 break;
586 case dwarf_q13:
587 reg_info.name = "q13";
588 break;
589 case dwarf_q14:
590 reg_info.name = "q14";
591 break;
592 case dwarf_q15:
593 reg_info.name = "q15";
594 break;
595
596 default:
597 return false;
598 }
599 return true;
600 }
601
602 // A8.6.50
603 // Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
CountITSize(uint32_t ITMask)604 static uint32_t CountITSize(uint32_t ITMask) {
605 // First count the trailing zeros of the IT mask.
606 uint32_t TZ = llvm::countTrailingZeros(ITMask);
607 if (TZ > 3) {
608 return 0;
609 }
610 return (4 - TZ);
611 }
612
613 // Init ITState. Note that at least one bit is always 1 in mask.
InitIT(uint32_t bits7_0)614 bool ITSession::InitIT(uint32_t bits7_0) {
615 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
616 if (ITCounter == 0)
617 return false;
618
619 // A8.6.50 IT
620 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
621 if (FirstCond == 0xF) {
622 return false;
623 }
624 if (FirstCond == 0xE && ITCounter != 1) {
625 return false;
626 }
627
628 ITState = bits7_0;
629 return true;
630 }
631
632 // Update ITState if necessary.
ITAdvance()633 void ITSession::ITAdvance() {
634 // assert(ITCounter);
635 --ITCounter;
636 if (ITCounter == 0)
637 ITState = 0;
638 else {
639 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
640 SetBits32(ITState, 4, 0, NewITState4_0);
641 }
642 }
643
644 // Return true if we're inside an IT Block.
InITBlock()645 bool ITSession::InITBlock() { return ITCounter != 0; }
646
647 // Return true if we're the last instruction inside an IT Block.
LastInITBlock()648 bool ITSession::LastInITBlock() { return ITCounter == 1; }
649
650 // Get condition bits for the current thumb instruction.
GetCond()651 uint32_t ITSession::GetCond() {
652 if (InITBlock())
653 return Bits32(ITState, 7, 4);
654 else
655 return COND_AL;
656 }
657
658 // ARM constants used during decoding
659 #define REG_RD 0
660 #define LDM_REGLIST 1
661 #define SP_REG 13
662 #define LR_REG 14
663 #define PC_REG 15
664 #define PC_REGLIST_BIT 0x8000
665
666 #define ARMv4 (1u << 0)
667 #define ARMv4T (1u << 1)
668 #define ARMv5T (1u << 2)
669 #define ARMv5TE (1u << 3)
670 #define ARMv5TEJ (1u << 4)
671 #define ARMv6 (1u << 5)
672 #define ARMv6K (1u << 6)
673 #define ARMv6T2 (1u << 7)
674 #define ARMv7 (1u << 8)
675 #define ARMv7S (1u << 9)
676 #define ARMv8 (1u << 10)
677 #define ARMvAll (0xffffffffu)
678
679 #define ARMV4T_ABOVE \
680 (ARMv4T | ARMv5T | ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | \
681 ARMv7S | ARMv8)
682 #define ARMV5_ABOVE \
683 (ARMv5T | ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | \
684 ARMv8)
685 #define ARMV5TE_ABOVE \
686 (ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
687 #define ARMV5J_ABOVE \
688 (ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
689 #define ARMV6_ABOVE (ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
690 #define ARMV6T2_ABOVE (ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
691 #define ARMV7_ABOVE (ARMv7 | ARMv7S | ARMv8)
692
693 #define No_VFP 0
694 #define VFPv1 (1u << 1)
695 #define VFPv2 (1u << 2)
696 #define VFPv3 (1u << 3)
697 #define AdvancedSIMD (1u << 4)
698
699 #define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD)
700 #define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD)
701 #define VFPv2v3 (VFPv2 | VFPv3)
702
703 //
704 // EmulateInstructionARM implementation
705 //
706
Initialize()707 void EmulateInstructionARM::Initialize() {
708 PluginManager::RegisterPlugin(GetPluginNameStatic(),
709 GetPluginDescriptionStatic(), CreateInstance);
710 }
711
Terminate()712 void EmulateInstructionARM::Terminate() {
713 PluginManager::UnregisterPlugin(CreateInstance);
714 }
715
GetPluginDescriptionStatic()716 llvm::StringRef EmulateInstructionARM::GetPluginDescriptionStatic() {
717 return "Emulate instructions for the ARM architecture.";
718 }
719
720 EmulateInstruction *
CreateInstance(const ArchSpec & arch,InstructionType inst_type)721 EmulateInstructionARM::CreateInstance(const ArchSpec &arch,
722 InstructionType inst_type) {
723 if (EmulateInstructionARM::SupportsEmulatingInstructionsOfTypeStatic(
724 inst_type)) {
725 if (arch.GetTriple().getArch() == llvm::Triple::arm) {
726 std::unique_ptr<EmulateInstructionARM> emulate_insn_up(
727 new EmulateInstructionARM(arch));
728
729 if (emulate_insn_up)
730 return emulate_insn_up.release();
731 } else if (arch.GetTriple().getArch() == llvm::Triple::thumb) {
732 std::unique_ptr<EmulateInstructionARM> emulate_insn_up(
733 new EmulateInstructionARM(arch));
734
735 if (emulate_insn_up)
736 return emulate_insn_up.release();
737 }
738 }
739
740 return nullptr;
741 }
742
SetTargetTriple(const ArchSpec & arch)743 bool EmulateInstructionARM::SetTargetTriple(const ArchSpec &arch) {
744 if (arch.GetTriple().getArch() == llvm::Triple::arm)
745 return true;
746 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
747 return true;
748
749 return false;
750 }
751
752 // Write "bits (32) UNKNOWN" to memory address "address". Helper function for
753 // many ARM instructions.
WriteBits32UnknownToMemory(addr_t address)754 bool EmulateInstructionARM::WriteBits32UnknownToMemory(addr_t address) {
755 EmulateInstruction::Context context;
756 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
757 context.SetNoArgs();
758
759 uint32_t random_data = rand();
760 const uint32_t addr_byte_size = GetAddressByteSize();
761
762 return MemAWrite(context, address, random_data, addr_byte_size);
763 }
764
765 // Write "bits (32) UNKNOWN" to register n. Helper function for many ARM
766 // instructions.
WriteBits32Unknown(int n)767 bool EmulateInstructionARM::WriteBits32Unknown(int n) {
768 EmulateInstruction::Context context;
769 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
770 context.SetNoArgs();
771
772 bool success;
773 uint32_t data =
774 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
775
776 if (!success)
777 return false;
778
779 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, data))
780 return false;
781
782 return true;
783 }
784
GetRegisterInfo(lldb::RegisterKind reg_kind,uint32_t reg_num,RegisterInfo & reg_info)785 bool EmulateInstructionARM::GetRegisterInfo(lldb::RegisterKind reg_kind,
786 uint32_t reg_num,
787 RegisterInfo ®_info) {
788 if (reg_kind == eRegisterKindGeneric) {
789 switch (reg_num) {
790 case LLDB_REGNUM_GENERIC_PC:
791 reg_kind = eRegisterKindDWARF;
792 reg_num = dwarf_pc;
793 break;
794 case LLDB_REGNUM_GENERIC_SP:
795 reg_kind = eRegisterKindDWARF;
796 reg_num = dwarf_sp;
797 break;
798 case LLDB_REGNUM_GENERIC_FP:
799 reg_kind = eRegisterKindDWARF;
800 reg_num = dwarf_r7;
801 break;
802 case LLDB_REGNUM_GENERIC_RA:
803 reg_kind = eRegisterKindDWARF;
804 reg_num = dwarf_lr;
805 break;
806 case LLDB_REGNUM_GENERIC_FLAGS:
807 reg_kind = eRegisterKindDWARF;
808 reg_num = dwarf_cpsr;
809 break;
810 default:
811 return false;
812 }
813 }
814
815 if (reg_kind == eRegisterKindDWARF)
816 return GetARMDWARFRegisterInfo(reg_num, reg_info);
817 return false;
818 }
819
GetFramePointerRegisterNumber() const820 uint32_t EmulateInstructionARM::GetFramePointerRegisterNumber() const {
821 if (m_arch.GetTriple().isAndroid())
822 return LLDB_INVALID_REGNUM; // Don't use frame pointer on android
823 bool is_apple = false;
824 if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)
825 is_apple = true;
826 switch (m_arch.GetTriple().getOS()) {
827 case llvm::Triple::Darwin:
828 case llvm::Triple::MacOSX:
829 case llvm::Triple::IOS:
830 case llvm::Triple::TvOS:
831 case llvm::Triple::WatchOS:
832 // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS:
833 is_apple = true;
834 break;
835 default:
836 break;
837 }
838
839 /* On Apple iOS et al, the frame pointer register is always r7.
840 * Typically on other ARM systems, thumb code uses r7; arm code uses r11.
841 * Windows on ARM, which is in thumb mode, uses r11 though.
842 */
843
844 uint32_t fp_regnum = 11;
845
846 if (is_apple)
847 fp_regnum = 7;
848
849 if (m_opcode_mode == eModeThumb && !m_arch.GetTriple().isOSWindows())
850 fp_regnum = 7;
851
852 return fp_regnum;
853 }
854
GetFramePointerDWARFRegisterNumber() const855 uint32_t EmulateInstructionARM::GetFramePointerDWARFRegisterNumber() const {
856 bool is_apple = false;
857 if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)
858 is_apple = true;
859 switch (m_arch.GetTriple().getOS()) {
860 case llvm::Triple::Darwin:
861 case llvm::Triple::MacOSX:
862 case llvm::Triple::IOS:
863 is_apple = true;
864 break;
865 default:
866 break;
867 }
868
869 /* On Apple iOS et al, the frame pointer register is always r7.
870 * Typically on other ARM systems, thumb code uses r7; arm code uses r11.
871 * Windows on ARM, which is in thumb mode, uses r11 though.
872 */
873
874 uint32_t fp_regnum = dwarf_r11;
875
876 if (is_apple)
877 fp_regnum = dwarf_r7;
878
879 if (m_opcode_mode == eModeThumb && !m_arch.GetTriple().isOSWindows())
880 fp_regnum = dwarf_r7;
881
882 return fp_regnum;
883 }
884
885 // Push Multiple Registers stores multiple registers to the stack, storing to
886 // consecutive memory locations ending just below the address in SP, and
887 // updates
888 // SP to point to the start of the stored data.
EmulatePUSH(const uint32_t opcode,const ARMEncoding encoding)889 bool EmulateInstructionARM::EmulatePUSH(const uint32_t opcode,
890 const ARMEncoding encoding) {
891 #if 0
892 // ARM pseudo code...
893 if (ConditionPassed())
894 {
895 EncodingSpecificOperations();
896 NullCheckIfThumbEE(13);
897 address = SP - 4*BitCount(registers);
898
899 for (i = 0 to 14)
900 {
901 if (registers<i> == '1')
902 {
903 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
904 MemA[address,4] = bits(32) UNKNOWN;
905 else
906 MemA[address,4] = R[i];
907 address = address + 4;
908 }
909 }
910
911 if (registers<15> == '1') // Only possible for encoding A1 or A2
912 MemA[address,4] = PCStoreValue();
913
914 SP = SP - 4*BitCount(registers);
915 }
916 #endif
917
918 bool success = false;
919 if (ConditionPassed(opcode)) {
920 const uint32_t addr_byte_size = GetAddressByteSize();
921 const addr_t sp = ReadCoreReg(SP_REG, &success);
922 if (!success)
923 return false;
924 uint32_t registers = 0;
925 uint32_t Rt; // the source register
926 switch (encoding) {
927 case eEncodingT1:
928 registers = Bits32(opcode, 7, 0);
929 // The M bit represents LR.
930 if (Bit32(opcode, 8))
931 registers |= (1u << 14);
932 // if BitCount(registers) < 1 then UNPREDICTABLE;
933 if (BitCount(registers) < 1)
934 return false;
935 break;
936 case eEncodingT2:
937 // Ignore bits 15 & 13.
938 registers = Bits32(opcode, 15, 0) & ~0xa000;
939 // if BitCount(registers) < 2 then UNPREDICTABLE;
940 if (BitCount(registers) < 2)
941 return false;
942 break;
943 case eEncodingT3:
944 Rt = Bits32(opcode, 15, 12);
945 // if BadReg(t) then UNPREDICTABLE;
946 if (BadReg(Rt))
947 return false;
948 registers = (1u << Rt);
949 break;
950 case eEncodingA1:
951 registers = Bits32(opcode, 15, 0);
952 // Instead of return false, let's handle the following case as well,
953 // which amounts to pushing one reg onto the full descending stacks.
954 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
955 break;
956 case eEncodingA2:
957 Rt = Bits32(opcode, 15, 12);
958 // if t == 13 then UNPREDICTABLE;
959 if (Rt == dwarf_sp)
960 return false;
961 registers = (1u << Rt);
962 break;
963 default:
964 return false;
965 }
966 addr_t sp_offset = addr_byte_size * BitCount(registers);
967 addr_t addr = sp - sp_offset;
968 uint32_t i;
969
970 EmulateInstruction::Context context;
971 context.type = EmulateInstruction::eContextPushRegisterOnStack;
972 RegisterInfo reg_info;
973 RegisterInfo sp_reg;
974 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
975 for (i = 0; i < 15; ++i) {
976 if (BitIsSet(registers, i)) {
977 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, reg_info);
978 context.SetRegisterToRegisterPlusOffset(reg_info, sp_reg, addr - sp);
979 uint32_t reg_value = ReadCoreReg(i, &success);
980 if (!success)
981 return false;
982 if (!MemAWrite(context, addr, reg_value, addr_byte_size))
983 return false;
984 addr += addr_byte_size;
985 }
986 }
987
988 if (BitIsSet(registers, 15)) {
989 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, reg_info);
990 context.SetRegisterToRegisterPlusOffset(reg_info, sp_reg, addr - sp);
991 const uint32_t pc = ReadCoreReg(PC_REG, &success);
992 if (!success)
993 return false;
994 if (!MemAWrite(context, addr, pc, addr_byte_size))
995 return false;
996 }
997
998 context.type = EmulateInstruction::eContextAdjustStackPointer;
999 context.SetImmediateSigned(-sp_offset);
1000
1001 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1002 LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
1003 return false;
1004 }
1005 return true;
1006 }
1007
1008 // Pop Multiple Registers loads multiple registers from the stack, loading from
1009 // consecutive memory locations staring at the address in SP, and updates
1010 // SP to point just above the loaded data.
EmulatePOP(const uint32_t opcode,const ARMEncoding encoding)1011 bool EmulateInstructionARM::EmulatePOP(const uint32_t opcode,
1012 const ARMEncoding encoding) {
1013 #if 0
1014 // ARM pseudo code...
1015 if (ConditionPassed())
1016 {
1017 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
1018 address = SP;
1019 for i = 0 to 14
1020 if registers<i> == '1' then
1021 R[i] = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
1022 if registers<15> == '1' then
1023 if UnalignedAllowed then
1024 LoadWritePC(MemU[address,4]);
1025 else
1026 LoadWritePC(MemA[address,4]);
1027 if registers<13> == '0' then SP = SP + 4*BitCount(registers);
1028 if registers<13> == '1' then SP = bits(32) UNKNOWN;
1029 }
1030 #endif
1031
1032 bool success = false;
1033
1034 if (ConditionPassed(opcode)) {
1035 const uint32_t addr_byte_size = GetAddressByteSize();
1036 const addr_t sp = ReadCoreReg(SP_REG, &success);
1037 if (!success)
1038 return false;
1039 uint32_t registers = 0;
1040 uint32_t Rt; // the destination register
1041 switch (encoding) {
1042 case eEncodingT1:
1043 registers = Bits32(opcode, 7, 0);
1044 // The P bit represents PC.
1045 if (Bit32(opcode, 8))
1046 registers |= (1u << 15);
1047 // if BitCount(registers) < 1 then UNPREDICTABLE;
1048 if (BitCount(registers) < 1)
1049 return false;
1050 break;
1051 case eEncodingT2:
1052 // Ignore bit 13.
1053 registers = Bits32(opcode, 15, 0) & ~0x2000;
1054 // if BitCount(registers) < 2 || (P == '1' && M == '1') then
1055 // UNPREDICTABLE;
1056 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
1057 return false;
1058 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
1059 // UNPREDICTABLE;
1060 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
1061 return false;
1062 break;
1063 case eEncodingT3:
1064 Rt = Bits32(opcode, 15, 12);
1065 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then
1066 // UNPREDICTABLE;
1067 if (Rt == 13)
1068 return false;
1069 if (Rt == 15 && InITBlock() && !LastInITBlock())
1070 return false;
1071 registers = (1u << Rt);
1072 break;
1073 case eEncodingA1:
1074 registers = Bits32(opcode, 15, 0);
1075 // Instead of return false, let's handle the following case as well,
1076 // which amounts to popping one reg from the full descending stacks.
1077 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
1078
1079 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
1080 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
1081 return false;
1082 break;
1083 case eEncodingA2:
1084 Rt = Bits32(opcode, 15, 12);
1085 // if t == 13 then UNPREDICTABLE;
1086 if (Rt == dwarf_sp)
1087 return false;
1088 registers = (1u << Rt);
1089 break;
1090 default:
1091 return false;
1092 }
1093 addr_t sp_offset = addr_byte_size * BitCount(registers);
1094 addr_t addr = sp;
1095 uint32_t i, data;
1096
1097 EmulateInstruction::Context context;
1098 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1099
1100 RegisterInfo sp_reg;
1101 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
1102
1103 for (i = 0; i < 15; ++i) {
1104 if (BitIsSet(registers, i)) {
1105 context.SetAddress(addr);
1106 data = MemARead(context, addr, 4, 0, &success);
1107 if (!success)
1108 return false;
1109 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
1110 data))
1111 return false;
1112 addr += addr_byte_size;
1113 }
1114 }
1115
1116 if (BitIsSet(registers, 15)) {
1117 context.SetRegisterPlusOffset(sp_reg, addr - sp);
1118 data = MemARead(context, addr, 4, 0, &success);
1119 if (!success)
1120 return false;
1121 // In ARMv5T and above, this is an interworking branch.
1122 if (!LoadWritePC(context, data))
1123 return false;
1124 // addr += addr_byte_size;
1125 }
1126
1127 context.type = EmulateInstruction::eContextAdjustStackPointer;
1128 context.SetImmediateSigned(sp_offset);
1129
1130 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1131 LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1132 return false;
1133 }
1134 return true;
1135 }
1136
1137 // Set r7 or ip to point to saved value residing within the stack.
1138 // ADD (SP plus immediate)
EmulateADDRdSPImm(const uint32_t opcode,const ARMEncoding encoding)1139 bool EmulateInstructionARM::EmulateADDRdSPImm(const uint32_t opcode,
1140 const ARMEncoding encoding) {
1141 #if 0
1142 // ARM pseudo code...
1143 if (ConditionPassed())
1144 {
1145 EncodingSpecificOperations();
1146 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
1147 if d == 15 then
1148 ALUWritePC(result); // setflags is always FALSE here
1149 else
1150 R[d] = result;
1151 if setflags then
1152 APSR.N = result<31>;
1153 APSR.Z = IsZeroBit(result);
1154 APSR.C = carry;
1155 APSR.V = overflow;
1156 }
1157 #endif
1158
1159 bool success = false;
1160
1161 if (ConditionPassed(opcode)) {
1162 const addr_t sp = ReadCoreReg(SP_REG, &success);
1163 if (!success)
1164 return false;
1165 uint32_t Rd; // the destination register
1166 uint32_t imm32;
1167 switch (encoding) {
1168 case eEncodingT1:
1169 Rd = 7;
1170 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
1171 break;
1172 case eEncodingA1:
1173 Rd = Bits32(opcode, 15, 12);
1174 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1175 break;
1176 default:
1177 return false;
1178 }
1179 addr_t sp_offset = imm32;
1180 addr_t addr = sp + sp_offset; // a pointer to the stack area
1181
1182 EmulateInstruction::Context context;
1183 if (Rd == GetFramePointerRegisterNumber())
1184 context.type = eContextSetFramePointer;
1185 else
1186 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1187 RegisterInfo sp_reg;
1188 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
1189 context.SetRegisterPlusOffset(sp_reg, sp_offset);
1190
1191 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd,
1192 addr))
1193 return false;
1194 }
1195 return true;
1196 }
1197
1198 // Set r7 or ip to the current stack pointer.
1199 // MOV (register)
EmulateMOVRdSP(const uint32_t opcode,const ARMEncoding encoding)1200 bool EmulateInstructionARM::EmulateMOVRdSP(const uint32_t opcode,
1201 const ARMEncoding encoding) {
1202 #if 0
1203 // ARM pseudo code...
1204 if (ConditionPassed())
1205 {
1206 EncodingSpecificOperations();
1207 result = R[m];
1208 if d == 15 then
1209 ALUWritePC(result); // setflags is always FALSE here
1210 else
1211 R[d] = result;
1212 if setflags then
1213 APSR.N = result<31>;
1214 APSR.Z = IsZeroBit(result);
1215 // APSR.C unchanged
1216 // APSR.V unchanged
1217 }
1218 #endif
1219
1220 bool success = false;
1221
1222 if (ConditionPassed(opcode)) {
1223 const addr_t sp = ReadCoreReg(SP_REG, &success);
1224 if (!success)
1225 return false;
1226 uint32_t Rd; // the destination register
1227 switch (encoding) {
1228 case eEncodingT1:
1229 Rd = 7;
1230 break;
1231 case eEncodingA1:
1232 Rd = 12;
1233 break;
1234 default:
1235 return false;
1236 }
1237
1238 EmulateInstruction::Context context;
1239 if (Rd == GetFramePointerRegisterNumber())
1240 context.type = EmulateInstruction::eContextSetFramePointer;
1241 else
1242 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1243 RegisterInfo sp_reg;
1244 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
1245 context.SetRegisterPlusOffset(sp_reg, 0);
1246
1247 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
1248 return false;
1249 }
1250 return true;
1251 }
1252
1253 // Move from high register (r8-r15) to low register (r0-r7).
1254 // MOV (register)
EmulateMOVLowHigh(const uint32_t opcode,const ARMEncoding encoding)1255 bool EmulateInstructionARM::EmulateMOVLowHigh(const uint32_t opcode,
1256 const ARMEncoding encoding) {
1257 return EmulateMOVRdRm(opcode, encoding);
1258 }
1259
1260 // Move from register to register.
1261 // MOV (register)
EmulateMOVRdRm(const uint32_t opcode,const ARMEncoding encoding)1262 bool EmulateInstructionARM::EmulateMOVRdRm(const uint32_t opcode,
1263 const ARMEncoding encoding) {
1264 #if 0
1265 // ARM pseudo code...
1266 if (ConditionPassed())
1267 {
1268 EncodingSpecificOperations();
1269 result = R[m];
1270 if d == 15 then
1271 ALUWritePC(result); // setflags is always FALSE here
1272 else
1273 R[d] = result;
1274 if setflags then
1275 APSR.N = result<31>;
1276 APSR.Z = IsZeroBit(result);
1277 // APSR.C unchanged
1278 // APSR.V unchanged
1279 }
1280 #endif
1281
1282 bool success = false;
1283
1284 if (ConditionPassed(opcode)) {
1285 uint32_t Rm; // the source register
1286 uint32_t Rd; // the destination register
1287 bool setflags;
1288 switch (encoding) {
1289 case eEncodingT1:
1290 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
1291 Rm = Bits32(opcode, 6, 3);
1292 setflags = false;
1293 if (Rd == 15 && InITBlock() && !LastInITBlock())
1294 return false;
1295 break;
1296 case eEncodingT2:
1297 Rd = Bits32(opcode, 2, 0);
1298 Rm = Bits32(opcode, 5, 3);
1299 setflags = true;
1300 if (InITBlock())
1301 return false;
1302 break;
1303 case eEncodingT3:
1304 Rd = Bits32(opcode, 11, 8);
1305 Rm = Bits32(opcode, 3, 0);
1306 setflags = BitIsSet(opcode, 20);
1307 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
1308 if (setflags && (BadReg(Rd) || BadReg(Rm)))
1309 return false;
1310 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then
1311 // UNPREDICTABLE;
1312 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
1313 return false;
1314 break;
1315 case eEncodingA1:
1316 Rd = Bits32(opcode, 15, 12);
1317 Rm = Bits32(opcode, 3, 0);
1318 setflags = BitIsSet(opcode, 20);
1319
1320 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1321 // instructions;
1322 if (Rd == 15 && setflags)
1323 return EmulateSUBSPcLrEtc(opcode, encoding);
1324 break;
1325 default:
1326 return false;
1327 }
1328 uint32_t result = ReadCoreReg(Rm, &success);
1329 if (!success)
1330 return false;
1331
1332 // The context specifies that Rm is to be moved into Rd.
1333 EmulateInstruction::Context context;
1334 if (Rd == 13)
1335 context.type = EmulateInstruction::eContextAdjustStackPointer;
1336 else if (Rd == GetFramePointerRegisterNumber() && Rm == 13)
1337 context.type = EmulateInstruction::eContextSetFramePointer;
1338 else
1339 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1340 RegisterInfo dwarf_reg;
1341 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
1342 context.SetRegisterPlusOffset(dwarf_reg, 0);
1343
1344 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
1345 return false;
1346 }
1347 return true;
1348 }
1349
1350 // Move (immediate) writes an immediate value to the destination register. It
1351 // can optionally update the condition flags based on the value.
1352 // MOV (immediate)
EmulateMOVRdImm(const uint32_t opcode,const ARMEncoding encoding)1353 bool EmulateInstructionARM::EmulateMOVRdImm(const uint32_t opcode,
1354 const ARMEncoding encoding) {
1355 #if 0
1356 // ARM pseudo code...
1357 if (ConditionPassed())
1358 {
1359 EncodingSpecificOperations();
1360 result = imm32;
1361 if d == 15 then // Can only occur for ARM encoding
1362 ALUWritePC(result); // setflags is always FALSE here
1363 else
1364 R[d] = result;
1365 if setflags then
1366 APSR.N = result<31>;
1367 APSR.Z = IsZeroBit(result);
1368 APSR.C = carry;
1369 // APSR.V unchanged
1370 }
1371 #endif
1372
1373 if (ConditionPassed(opcode)) {
1374 uint32_t Rd; // the destination register
1375 uint32_t imm32; // the immediate value to be written to Rd
1376 uint32_t carry =
1377 0; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
1378 // for setflags == false, this value is a don't care initialized to
1379 // 0 to silence the static analyzer
1380 bool setflags;
1381 switch (encoding) {
1382 case eEncodingT1:
1383 Rd = Bits32(opcode, 10, 8);
1384 setflags = !InITBlock();
1385 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
1386 carry = APSR_C;
1387
1388 break;
1389
1390 case eEncodingT2:
1391 Rd = Bits32(opcode, 11, 8);
1392 setflags = BitIsSet(opcode, 20);
1393 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
1394 if (BadReg(Rd))
1395 return false;
1396
1397 break;
1398
1399 case eEncodingT3: {
1400 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8,
1401 // 32);
1402 Rd = Bits32(opcode, 11, 8);
1403 setflags = false;
1404 uint32_t imm4 = Bits32(opcode, 19, 16);
1405 uint32_t imm3 = Bits32(opcode, 14, 12);
1406 uint32_t i = Bit32(opcode, 26);
1407 uint32_t imm8 = Bits32(opcode, 7, 0);
1408 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
1409
1410 // if BadReg(d) then UNPREDICTABLE;
1411 if (BadReg(Rd))
1412 return false;
1413 } break;
1414
1415 case eEncodingA1:
1416 // d = UInt(Rd); setflags = (S == '1'); (imm32, carry) =
1417 // ARMExpandImm_C(imm12, APSR.C);
1418 Rd = Bits32(opcode, 15, 12);
1419 setflags = BitIsSet(opcode, 20);
1420 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
1421
1422 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1423 // instructions;
1424 if ((Rd == 15) && setflags)
1425 return EmulateSUBSPcLrEtc(opcode, encoding);
1426
1427 break;
1428
1429 case eEncodingA2: {
1430 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
1431 Rd = Bits32(opcode, 15, 12);
1432 setflags = false;
1433 uint32_t imm4 = Bits32(opcode, 19, 16);
1434 uint32_t imm12 = Bits32(opcode, 11, 0);
1435 imm32 = (imm4 << 12) | imm12;
1436
1437 // if d == 15 then UNPREDICTABLE;
1438 if (Rd == 15)
1439 return false;
1440 } break;
1441
1442 default:
1443 return false;
1444 }
1445 uint32_t result = imm32;
1446
1447 // The context specifies that an immediate is to be moved into Rd.
1448 EmulateInstruction::Context context;
1449 context.type = EmulateInstruction::eContextImmediate;
1450 context.SetNoArgs();
1451
1452 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1453 return false;
1454 }
1455 return true;
1456 }
1457
1458 // MUL multiplies two register values. The least significant 32 bits of the
1459 // result are written to the destination
1460 // register. These 32 bits do not depend on whether the source register values
1461 // are considered to be signed values or unsigned values.
1462 //
1463 // Optionally, it can update the condition flags based on the result. In the
1464 // Thumb instruction set, this option is limited to only a few forms of the
1465 // instruction.
EmulateMUL(const uint32_t opcode,const ARMEncoding encoding)1466 bool EmulateInstructionARM::EmulateMUL(const uint32_t opcode,
1467 const ARMEncoding encoding) {
1468 #if 0
1469 if ConditionPassed() then
1470 EncodingSpecificOperations();
1471 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
1472 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
1473 result = operand1 * operand2;
1474 R[d] = result<31:0>;
1475 if setflags then
1476 APSR.N = result<31>;
1477 APSR.Z = IsZeroBit(result);
1478 if ArchVersion() == 4 then
1479 APSR.C = bit UNKNOWN;
1480 // else APSR.C unchanged
1481 // APSR.V always unchanged
1482 #endif
1483
1484 if (ConditionPassed(opcode)) {
1485 uint32_t d;
1486 uint32_t n;
1487 uint32_t m;
1488 bool setflags;
1489
1490 // EncodingSpecificOperations();
1491 switch (encoding) {
1492 case eEncodingT1:
1493 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
1494 d = Bits32(opcode, 2, 0);
1495 n = Bits32(opcode, 5, 3);
1496 m = Bits32(opcode, 2, 0);
1497 setflags = !InITBlock();
1498
1499 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
1500 if ((ArchVersion() < ARMv6) && (d == n))
1501 return false;
1502
1503 break;
1504
1505 case eEncodingT2:
1506 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
1507 d = Bits32(opcode, 11, 8);
1508 n = Bits32(opcode, 19, 16);
1509 m = Bits32(opcode, 3, 0);
1510 setflags = false;
1511
1512 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
1513 if (BadReg(d) || BadReg(n) || BadReg(m))
1514 return false;
1515
1516 break;
1517
1518 case eEncodingA1:
1519 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
1520 d = Bits32(opcode, 19, 16);
1521 n = Bits32(opcode, 3, 0);
1522 m = Bits32(opcode, 11, 8);
1523 setflags = BitIsSet(opcode, 20);
1524
1525 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
1526 if ((d == 15) || (n == 15) || (m == 15))
1527 return false;
1528
1529 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
1530 if ((ArchVersion() < ARMv6) && (d == n))
1531 return false;
1532
1533 break;
1534
1535 default:
1536 return false;
1537 }
1538
1539 bool success = false;
1540
1541 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final
1542 // results
1543 uint64_t operand1 =
1544 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1545 if (!success)
1546 return false;
1547
1548 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final
1549 // results
1550 uint64_t operand2 =
1551 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
1552 if (!success)
1553 return false;
1554
1555 // result = operand1 * operand2;
1556 uint64_t result = operand1 * operand2;
1557
1558 // R[d] = result<31:0>;
1559 RegisterInfo op1_reg;
1560 RegisterInfo op2_reg;
1561 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, op1_reg);
1562 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, op2_reg);
1563
1564 EmulateInstruction::Context context;
1565 context.type = eContextArithmetic;
1566 context.SetRegisterRegisterOperands(op1_reg, op2_reg);
1567
1568 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
1569 (0x0000ffff & result)))
1570 return false;
1571
1572 // if setflags then
1573 if (setflags) {
1574 // APSR.N = result<31>;
1575 // APSR.Z = IsZeroBit(result);
1576 m_new_inst_cpsr = m_opcode_cpsr;
1577 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, 31));
1578 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
1579 if (m_new_inst_cpsr != m_opcode_cpsr) {
1580 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1581 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
1582 return false;
1583 }
1584
1585 // if ArchVersion() == 4 then
1586 // APSR.C = bit UNKNOWN;
1587 }
1588 }
1589 return true;
1590 }
1591
1592 // Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to
1593 // the destination register. It can optionally update the condition flags based
1594 // on the value.
EmulateMVNImm(const uint32_t opcode,const ARMEncoding encoding)1595 bool EmulateInstructionARM::EmulateMVNImm(const uint32_t opcode,
1596 const ARMEncoding encoding) {
1597 #if 0
1598 // ARM pseudo code...
1599 if (ConditionPassed())
1600 {
1601 EncodingSpecificOperations();
1602 result = NOT(imm32);
1603 if d == 15 then // Can only occur for ARM encoding
1604 ALUWritePC(result); // setflags is always FALSE here
1605 else
1606 R[d] = result;
1607 if setflags then
1608 APSR.N = result<31>;
1609 APSR.Z = IsZeroBit(result);
1610 APSR.C = carry;
1611 // APSR.V unchanged
1612 }
1613 #endif
1614
1615 if (ConditionPassed(opcode)) {
1616 uint32_t Rd; // the destination register
1617 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
1618 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
1619 bool setflags;
1620 switch (encoding) {
1621 case eEncodingT1:
1622 Rd = Bits32(opcode, 11, 8);
1623 setflags = BitIsSet(opcode, 20);
1624 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
1625 break;
1626 case eEncodingA1:
1627 Rd = Bits32(opcode, 15, 12);
1628 setflags = BitIsSet(opcode, 20);
1629 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
1630
1631 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1632 // instructions;
1633 if (Rd == 15 && setflags)
1634 return EmulateSUBSPcLrEtc(opcode, encoding);
1635 break;
1636 default:
1637 return false;
1638 }
1639 uint32_t result = ~imm32;
1640
1641 // The context specifies that an immediate is to be moved into Rd.
1642 EmulateInstruction::Context context;
1643 context.type = EmulateInstruction::eContextImmediate;
1644 context.SetNoArgs();
1645
1646 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1647 return false;
1648 }
1649 return true;
1650 }
1651
1652 // Bitwise NOT (register) writes the bitwise inverse of a register value to the
1653 // destination register. It can optionally update the condition flags based on
1654 // the result.
EmulateMVNReg(const uint32_t opcode,const ARMEncoding encoding)1655 bool EmulateInstructionARM::EmulateMVNReg(const uint32_t opcode,
1656 const ARMEncoding encoding) {
1657 #if 0
1658 // ARM pseudo code...
1659 if (ConditionPassed())
1660 {
1661 EncodingSpecificOperations();
1662 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
1663 result = NOT(shifted);
1664 if d == 15 then // Can only occur for ARM encoding
1665 ALUWritePC(result); // setflags is always FALSE here
1666 else
1667 R[d] = result;
1668 if setflags then
1669 APSR.N = result<31>;
1670 APSR.Z = IsZeroBit(result);
1671 APSR.C = carry;
1672 // APSR.V unchanged
1673 }
1674 #endif
1675
1676 if (ConditionPassed(opcode)) {
1677 uint32_t Rm; // the source register
1678 uint32_t Rd; // the destination register
1679 ARM_ShifterType shift_t;
1680 uint32_t shift_n; // the shift applied to the value read from Rm
1681 bool setflags;
1682 uint32_t carry; // the carry bit after the shift operation
1683 switch (encoding) {
1684 case eEncodingT1:
1685 Rd = Bits32(opcode, 2, 0);
1686 Rm = Bits32(opcode, 5, 3);
1687 setflags = !InITBlock();
1688 shift_t = SRType_LSL;
1689 shift_n = 0;
1690 if (InITBlock())
1691 return false;
1692 break;
1693 case eEncodingT2:
1694 Rd = Bits32(opcode, 11, 8);
1695 Rm = Bits32(opcode, 3, 0);
1696 setflags = BitIsSet(opcode, 20);
1697 shift_n = DecodeImmShiftThumb(opcode, shift_t);
1698 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
1699 if (BadReg(Rd) || BadReg(Rm))
1700 return false;
1701 break;
1702 case eEncodingA1:
1703 Rd = Bits32(opcode, 15, 12);
1704 Rm = Bits32(opcode, 3, 0);
1705 setflags = BitIsSet(opcode, 20);
1706 shift_n = DecodeImmShiftARM(opcode, shift_t);
1707 break;
1708 default:
1709 return false;
1710 }
1711 bool success = false;
1712 uint32_t value = ReadCoreReg(Rm, &success);
1713 if (!success)
1714 return false;
1715
1716 uint32_t shifted =
1717 Shift_C(value, shift_t, shift_n, APSR_C, carry, &success);
1718 if (!success)
1719 return false;
1720 uint32_t result = ~shifted;
1721
1722 // The context specifies that an immediate is to be moved into Rd.
1723 EmulateInstruction::Context context;
1724 context.type = EmulateInstruction::eContextImmediate;
1725 context.SetNoArgs();
1726
1727 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1728 return false;
1729 }
1730 return true;
1731 }
1732
1733 // PC relative immediate load into register, possibly followed by ADD (SP plus
1734 // register).
1735 // LDR (literal)
EmulateLDRRtPCRelative(const uint32_t opcode,const ARMEncoding encoding)1736 bool EmulateInstructionARM::EmulateLDRRtPCRelative(const uint32_t opcode,
1737 const ARMEncoding encoding) {
1738 #if 0
1739 // ARM pseudo code...
1740 if (ConditionPassed())
1741 {
1742 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1743 base = Align(PC,4);
1744 address = if add then (base + imm32) else (base - imm32);
1745 data = MemU[address,4];
1746 if t == 15 then
1747 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1748 elsif UnalignedSupport() || address<1:0> = '00' then
1749 R[t] = data;
1750 else // Can only apply before ARMv7
1751 if CurrentInstrSet() == InstrSet_ARM then
1752 R[t] = ROR(data, 8*UInt(address<1:0>));
1753 else
1754 R[t] = bits(32) UNKNOWN;
1755 }
1756 #endif
1757
1758 if (ConditionPassed(opcode)) {
1759 bool success = false;
1760 const uint32_t pc = ReadCoreReg(PC_REG, &success);
1761 if (!success)
1762 return false;
1763
1764 // PC relative immediate load context
1765 EmulateInstruction::Context context;
1766 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1767 RegisterInfo pc_reg;
1768 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg);
1769 context.SetRegisterPlusOffset(pc_reg, 0);
1770
1771 uint32_t Rt; // the destination register
1772 uint32_t imm32; // immediate offset from the PC
1773 bool add; // +imm32 or -imm32?
1774 addr_t base; // the base address
1775 addr_t address; // the PC relative address
1776 uint32_t data; // the literal data value from the PC relative load
1777 switch (encoding) {
1778 case eEncodingT1:
1779 Rt = Bits32(opcode, 10, 8);
1780 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
1781 add = true;
1782 break;
1783 case eEncodingT2:
1784 Rt = Bits32(opcode, 15, 12);
1785 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1786 add = BitIsSet(opcode, 23);
1787 if (Rt == 15 && InITBlock() && !LastInITBlock())
1788 return false;
1789 break;
1790 default:
1791 return false;
1792 }
1793
1794 base = Align(pc, 4);
1795 if (add)
1796 address = base + imm32;
1797 else
1798 address = base - imm32;
1799
1800 context.SetRegisterPlusOffset(pc_reg, address - base);
1801 data = MemURead(context, address, 4, 0, &success);
1802 if (!success)
1803 return false;
1804
1805 if (Rt == 15) {
1806 if (Bits32(address, 1, 0) == 0) {
1807 // In ARMv5T and above, this is an interworking branch.
1808 if (!LoadWritePC(context, data))
1809 return false;
1810 } else
1811 return false;
1812 } else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) {
1813 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rt,
1814 data))
1815 return false;
1816 } else // We don't handle ARM for now.
1817 return false;
1818 }
1819 return true;
1820 }
1821
1822 // An add operation to adjust the SP.
1823 // ADD (SP plus immediate)
EmulateADDSPImm(const uint32_t opcode,const ARMEncoding encoding)1824 bool EmulateInstructionARM::EmulateADDSPImm(const uint32_t opcode,
1825 const ARMEncoding encoding) {
1826 #if 0
1827 // ARM pseudo code...
1828 if (ConditionPassed())
1829 {
1830 EncodingSpecificOperations();
1831 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
1832 if d == 15 then // Can only occur for ARM encoding
1833 ALUWritePC(result); // setflags is always FALSE here
1834 else
1835 R[d] = result;
1836 if setflags then
1837 APSR.N = result<31>;
1838 APSR.Z = IsZeroBit(result);
1839 APSR.C = carry;
1840 APSR.V = overflow;
1841 }
1842 #endif
1843
1844 bool success = false;
1845
1846 if (ConditionPassed(opcode)) {
1847 const addr_t sp = ReadCoreReg(SP_REG, &success);
1848 if (!success)
1849 return false;
1850 uint32_t imm32; // the immediate operand
1851 uint32_t d;
1852 bool setflags;
1853 switch (encoding) {
1854 case eEncodingT1:
1855 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
1856 d = Bits32(opcode, 10, 8);
1857 imm32 = (Bits32(opcode, 7, 0) << 2);
1858 setflags = false;
1859 break;
1860
1861 case eEncodingT2:
1862 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
1863 d = 13;
1864 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1865 setflags = false;
1866 break;
1867
1868 case eEncodingT3:
1869 // d = UInt(Rd); setflags = (S == "1"); imm32 =
1870 // ThumbExpandImm(i:imm3:imm8);
1871 d = Bits32(opcode, 11, 8);
1872 imm32 = ThumbExpandImm(opcode);
1873 setflags = Bit32(opcode, 20);
1874
1875 // if Rd == "1111" && S == "1" then SEE CMN (immediate);
1876 if (d == 15 && setflags == 1)
1877 return false; // CMN (immediate) not yet supported
1878
1879 // if d == 15 && S == "0" then UNPREDICTABLE;
1880 if (d == 15 && setflags == 0)
1881 return false;
1882 break;
1883
1884 case eEncodingT4: {
1885 // if Rn == '1111' then SEE ADR;
1886 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
1887 d = Bits32(opcode, 11, 8);
1888 setflags = false;
1889 uint32_t i = Bit32(opcode, 26);
1890 uint32_t imm3 = Bits32(opcode, 14, 12);
1891 uint32_t imm8 = Bits32(opcode, 7, 0);
1892 imm32 = (i << 11) | (imm3 << 8) | imm8;
1893
1894 // if d == 15 then UNPREDICTABLE;
1895 if (d == 15)
1896 return false;
1897 } break;
1898
1899 default:
1900 return false;
1901 }
1902 // (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
1903 AddWithCarryResult res = AddWithCarry(sp, imm32, 0);
1904
1905 EmulateInstruction::Context context;
1906 if (d == 13)
1907 context.type = EmulateInstruction::eContextAdjustStackPointer;
1908 else
1909 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1910
1911 RegisterInfo sp_reg;
1912 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
1913 context.SetRegisterPlusOffset(sp_reg, res.result - sp);
1914
1915 if (d == 15) {
1916 if (!ALUWritePC(context, res.result))
1917 return false;
1918 } else {
1919 // R[d] = result;
1920 // if setflags then
1921 // APSR.N = result<31>;
1922 // APSR.Z = IsZeroBit(result);
1923 // APSR.C = carry;
1924 // APSR.V = overflow;
1925 if (!WriteCoreRegOptionalFlags(context, res.result, d, setflags,
1926 res.carry_out, res.overflow))
1927 return false;
1928 }
1929 }
1930 return true;
1931 }
1932
1933 // An add operation to adjust the SP.
1934 // ADD (SP plus register)
EmulateADDSPRm(const uint32_t opcode,const ARMEncoding encoding)1935 bool EmulateInstructionARM::EmulateADDSPRm(const uint32_t opcode,
1936 const ARMEncoding encoding) {
1937 #if 0
1938 // ARM pseudo code...
1939 if (ConditionPassed())
1940 {
1941 EncodingSpecificOperations();
1942 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1943 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
1944 if d == 15 then
1945 ALUWritePC(result); // setflags is always FALSE here
1946 else
1947 R[d] = result;
1948 if setflags then
1949 APSR.N = result<31>;
1950 APSR.Z = IsZeroBit(result);
1951 APSR.C = carry;
1952 APSR.V = overflow;
1953 }
1954 #endif
1955
1956 bool success = false;
1957
1958 if (ConditionPassed(opcode)) {
1959 const addr_t sp = ReadCoreReg(SP_REG, &success);
1960 if (!success)
1961 return false;
1962 uint32_t Rm; // the second operand
1963 switch (encoding) {
1964 case eEncodingT2:
1965 Rm = Bits32(opcode, 6, 3);
1966 break;
1967 default:
1968 return false;
1969 }
1970 int32_t reg_value = ReadCoreReg(Rm, &success);
1971 if (!success)
1972 return false;
1973
1974 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1975
1976 EmulateInstruction::Context context;
1977 context.type = eContextArithmetic;
1978 RegisterInfo sp_reg;
1979 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
1980
1981 RegisterInfo other_reg;
1982 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, other_reg);
1983 context.SetRegisterRegisterOperands(sp_reg, other_reg);
1984
1985 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1986 LLDB_REGNUM_GENERIC_SP, addr))
1987 return false;
1988 }
1989 return true;
1990 }
1991
1992 // Branch with Link and Exchange Instruction Sets (immediate) calls a
1993 // subroutine at a PC-relative address, and changes instruction set from ARM to
1994 // Thumb, or from Thumb to ARM.
1995 // BLX (immediate)
EmulateBLXImmediate(const uint32_t opcode,const ARMEncoding encoding)1996 bool EmulateInstructionARM::EmulateBLXImmediate(const uint32_t opcode,
1997 const ARMEncoding encoding) {
1998 #if 0
1999 // ARM pseudo code...
2000 if (ConditionPassed())
2001 {
2002 EncodingSpecificOperations();
2003 if CurrentInstrSet() == InstrSet_ARM then
2004 LR = PC - 4;
2005 else
2006 LR = PC<31:1> : '1';
2007 if targetInstrSet == InstrSet_ARM then
2008 targetAddress = Align(PC,4) + imm32;
2009 else
2010 targetAddress = PC + imm32;
2011 SelectInstrSet(targetInstrSet);
2012 BranchWritePC(targetAddress);
2013 }
2014 #endif
2015
2016 bool success = true;
2017
2018 if (ConditionPassed(opcode)) {
2019 EmulateInstruction::Context context;
2020 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2021 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2022 if (!success)
2023 return false;
2024 addr_t lr; // next instruction address
2025 addr_t target; // target address
2026 int32_t imm32; // PC-relative offset
2027 switch (encoding) {
2028 case eEncodingT1: {
2029 lr = pc | 1u; // return address
2030 uint32_t S = Bit32(opcode, 26);
2031 uint32_t imm10 = Bits32(opcode, 25, 16);
2032 uint32_t J1 = Bit32(opcode, 13);
2033 uint32_t J2 = Bit32(opcode, 11);
2034 uint32_t imm11 = Bits32(opcode, 10, 0);
2035 uint32_t I1 = !(J1 ^ S);
2036 uint32_t I2 = !(J2 ^ S);
2037 uint32_t imm25 =
2038 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
2039 imm32 = llvm::SignExtend32<25>(imm25);
2040 target = pc + imm32;
2041 SelectInstrSet(eModeThumb);
2042 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2043 if (InITBlock() && !LastInITBlock())
2044 return false;
2045 break;
2046 }
2047 case eEncodingT2: {
2048 lr = pc | 1u; // return address
2049 uint32_t S = Bit32(opcode, 26);
2050 uint32_t imm10H = Bits32(opcode, 25, 16);
2051 uint32_t J1 = Bit32(opcode, 13);
2052 uint32_t J2 = Bit32(opcode, 11);
2053 uint32_t imm10L = Bits32(opcode, 10, 1);
2054 uint32_t I1 = !(J1 ^ S);
2055 uint32_t I2 = !(J2 ^ S);
2056 uint32_t imm25 =
2057 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
2058 imm32 = llvm::SignExtend32<25>(imm25);
2059 target = Align(pc, 4) + imm32;
2060 SelectInstrSet(eModeARM);
2061 context.SetISAAndImmediateSigned(eModeARM, 4 + imm32);
2062 if (InITBlock() && !LastInITBlock())
2063 return false;
2064 break;
2065 }
2066 case eEncodingA1:
2067 lr = pc - 4; // return address
2068 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
2069 target = Align(pc, 4) + imm32;
2070 SelectInstrSet(eModeARM);
2071 context.SetISAAndImmediateSigned(eModeARM, 8 + imm32);
2072 break;
2073 case eEncodingA2:
2074 lr = pc - 4; // return address
2075 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 |
2076 Bits32(opcode, 24, 24) << 1);
2077 target = pc + imm32;
2078 SelectInstrSet(eModeThumb);
2079 context.SetISAAndImmediateSigned(eModeThumb, 8 + imm32);
2080 break;
2081 default:
2082 return false;
2083 }
2084 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2085 LLDB_REGNUM_GENERIC_RA, lr))
2086 return false;
2087 if (!BranchWritePC(context, target))
2088 return false;
2089 if (m_opcode_cpsr != m_new_inst_cpsr)
2090 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2091 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2092 return false;
2093 }
2094 return true;
2095 }
2096
2097 // Branch with Link and Exchange (register) calls a subroutine at an address
2098 // and instruction set specified by a register.
2099 // BLX (register)
EmulateBLXRm(const uint32_t opcode,const ARMEncoding encoding)2100 bool EmulateInstructionARM::EmulateBLXRm(const uint32_t opcode,
2101 const ARMEncoding encoding) {
2102 #if 0
2103 // ARM pseudo code...
2104 if (ConditionPassed())
2105 {
2106 EncodingSpecificOperations();
2107 target = R[m];
2108 if CurrentInstrSet() == InstrSet_ARM then
2109 next_instr_addr = PC - 4;
2110 LR = next_instr_addr;
2111 else
2112 next_instr_addr = PC - 2;
2113 LR = next_instr_addr<31:1> : '1';
2114 BXWritePC(target);
2115 }
2116 #endif
2117
2118 bool success = false;
2119
2120 if (ConditionPassed(opcode)) {
2121 EmulateInstruction::Context context;
2122 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
2123 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2124 addr_t lr; // next instruction address
2125 if (!success)
2126 return false;
2127 uint32_t Rm; // the register with the target address
2128 switch (encoding) {
2129 case eEncodingT1:
2130 lr = (pc - 2) | 1u; // return address
2131 Rm = Bits32(opcode, 6, 3);
2132 // if m == 15 then UNPREDICTABLE;
2133 if (Rm == 15)
2134 return false;
2135 if (InITBlock() && !LastInITBlock())
2136 return false;
2137 break;
2138 case eEncodingA1:
2139 lr = pc - 4; // return address
2140 Rm = Bits32(opcode, 3, 0);
2141 // if m == 15 then UNPREDICTABLE;
2142 if (Rm == 15)
2143 return false;
2144 break;
2145 default:
2146 return false;
2147 }
2148 addr_t target = ReadCoreReg(Rm, &success);
2149 if (!success)
2150 return false;
2151 RegisterInfo dwarf_reg;
2152 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
2153 context.SetRegister(dwarf_reg);
2154 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2155 LLDB_REGNUM_GENERIC_RA, lr))
2156 return false;
2157 if (!BXWritePC(context, target))
2158 return false;
2159 }
2160 return true;
2161 }
2162
2163 // Branch and Exchange causes a branch to an address and instruction set
2164 // specified by a register.
EmulateBXRm(const uint32_t opcode,const ARMEncoding encoding)2165 bool EmulateInstructionARM::EmulateBXRm(const uint32_t opcode,
2166 const ARMEncoding encoding) {
2167 #if 0
2168 // ARM pseudo code...
2169 if (ConditionPassed())
2170 {
2171 EncodingSpecificOperations();
2172 BXWritePC(R[m]);
2173 }
2174 #endif
2175
2176 if (ConditionPassed(opcode)) {
2177 EmulateInstruction::Context context;
2178 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
2179 uint32_t Rm; // the register with the target address
2180 switch (encoding) {
2181 case eEncodingT1:
2182 Rm = Bits32(opcode, 6, 3);
2183 if (InITBlock() && !LastInITBlock())
2184 return false;
2185 break;
2186 case eEncodingA1:
2187 Rm = Bits32(opcode, 3, 0);
2188 break;
2189 default:
2190 return false;
2191 }
2192 bool success = false;
2193 addr_t target = ReadCoreReg(Rm, &success);
2194 if (!success)
2195 return false;
2196
2197 RegisterInfo dwarf_reg;
2198 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
2199 context.SetRegister(dwarf_reg);
2200 if (!BXWritePC(context, target))
2201 return false;
2202 }
2203 return true;
2204 }
2205
2206 // Branch and Exchange Jazelle attempts to change to Jazelle state. If the
2207 // attempt fails, it branches to an address and instruction set specified by a
2208 // register as though it were a BX instruction.
2209 //
2210 // TODO: Emulate Jazelle architecture?
2211 // We currently assume that switching to Jazelle state fails, thus
2212 // treating BXJ as a BX operation.
EmulateBXJRm(const uint32_t opcode,const ARMEncoding encoding)2213 bool EmulateInstructionARM::EmulateBXJRm(const uint32_t opcode,
2214 const ARMEncoding encoding) {
2215 #if 0
2216 // ARM pseudo code...
2217 if (ConditionPassed())
2218 {
2219 EncodingSpecificOperations();
2220 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
2221 BXWritePC(R[m]);
2222 else
2223 if JazelleAcceptsExecution() then
2224 SwitchToJazelleExecution();
2225 else
2226 SUBARCHITECTURE_DEFINED handler call;
2227 }
2228 #endif
2229
2230 if (ConditionPassed(opcode)) {
2231 EmulateInstruction::Context context;
2232 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
2233 uint32_t Rm; // the register with the target address
2234 switch (encoding) {
2235 case eEncodingT1:
2236 Rm = Bits32(opcode, 19, 16);
2237 if (BadReg(Rm))
2238 return false;
2239 if (InITBlock() && !LastInITBlock())
2240 return false;
2241 break;
2242 case eEncodingA1:
2243 Rm = Bits32(opcode, 3, 0);
2244 if (Rm == 15)
2245 return false;
2246 break;
2247 default:
2248 return false;
2249 }
2250 bool success = false;
2251 addr_t target = ReadCoreReg(Rm, &success);
2252 if (!success)
2253 return false;
2254
2255 RegisterInfo dwarf_reg;
2256 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
2257 context.SetRegister(dwarf_reg);
2258 if (!BXWritePC(context, target))
2259 return false;
2260 }
2261 return true;
2262 }
2263
2264 // Set r7 to point to some ip offset.
2265 // SUB (immediate)
EmulateSUBR7IPImm(const uint32_t opcode,const ARMEncoding encoding)2266 bool EmulateInstructionARM::EmulateSUBR7IPImm(const uint32_t opcode,
2267 const ARMEncoding encoding) {
2268 #if 0
2269 // ARM pseudo code...
2270 if (ConditionPassed())
2271 {
2272 EncodingSpecificOperations();
2273 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
2274 if d == 15 then // Can only occur for ARM encoding
2275 ALUWritePC(result); // setflags is always FALSE here
2276 else
2277 R[d] = result;
2278 if setflags then
2279 APSR.N = result<31>;
2280 APSR.Z = IsZeroBit(result);
2281 APSR.C = carry;
2282 APSR.V = overflow;
2283 }
2284 #endif
2285
2286 if (ConditionPassed(opcode)) {
2287 bool success = false;
2288 const addr_t ip = ReadCoreReg(12, &success);
2289 if (!success)
2290 return false;
2291 uint32_t imm32;
2292 switch (encoding) {
2293 case eEncodingA1:
2294 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2295 break;
2296 default:
2297 return false;
2298 }
2299 addr_t ip_offset = imm32;
2300 addr_t addr = ip - ip_offset; // the adjusted ip value
2301
2302 EmulateInstruction::Context context;
2303 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2304 RegisterInfo dwarf_reg;
2305 GetRegisterInfo(eRegisterKindDWARF, dwarf_r12, dwarf_reg);
2306 context.SetRegisterPlusOffset(dwarf_reg, -ip_offset);
2307
2308 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r7, addr))
2309 return false;
2310 }
2311 return true;
2312 }
2313
2314 // Set ip to point to some stack offset.
2315 // SUB (SP minus immediate)
EmulateSUBIPSPImm(const uint32_t opcode,const ARMEncoding encoding)2316 bool EmulateInstructionARM::EmulateSUBIPSPImm(const uint32_t opcode,
2317 const ARMEncoding encoding) {
2318 #if 0
2319 // ARM pseudo code...
2320 if (ConditionPassed())
2321 {
2322 EncodingSpecificOperations();
2323 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
2324 if d == 15 then // Can only occur for ARM encoding
2325 ALUWritePC(result); // setflags is always FALSE here
2326 else
2327 R[d] = result;
2328 if setflags then
2329 APSR.N = result<31>;
2330 APSR.Z = IsZeroBit(result);
2331 APSR.C = carry;
2332 APSR.V = overflow;
2333 }
2334 #endif
2335
2336 if (ConditionPassed(opcode)) {
2337 bool success = false;
2338 const addr_t sp = ReadCoreReg(SP_REG, &success);
2339 if (!success)
2340 return false;
2341 uint32_t imm32;
2342 switch (encoding) {
2343 case eEncodingA1:
2344 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2345 break;
2346 default:
2347 return false;
2348 }
2349 addr_t sp_offset = imm32;
2350 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
2351
2352 EmulateInstruction::Context context;
2353 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2354 RegisterInfo dwarf_reg;
2355 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, dwarf_reg);
2356 context.SetRegisterPlusOffset(dwarf_reg, -sp_offset);
2357
2358 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r12, addr))
2359 return false;
2360 }
2361 return true;
2362 }
2363
2364 // This instruction subtracts an immediate value from the SP value, and writes
2365 // the result to the destination register.
2366 //
2367 // If Rd == 13 => A sub operation to adjust the SP -- allocate space for local
2368 // storage.
EmulateSUBSPImm(const uint32_t opcode,const ARMEncoding encoding)2369 bool EmulateInstructionARM::EmulateSUBSPImm(const uint32_t opcode,
2370 const ARMEncoding encoding) {
2371 #if 0
2372 // ARM pseudo code...
2373 if (ConditionPassed())
2374 {
2375 EncodingSpecificOperations();
2376 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
2377 if d == 15 then // Can only occur for ARM encoding
2378 ALUWritePC(result); // setflags is always FALSE here
2379 else
2380 R[d] = result;
2381 if setflags then
2382 APSR.N = result<31>;
2383 APSR.Z = IsZeroBit(result);
2384 APSR.C = carry;
2385 APSR.V = overflow;
2386 }
2387 #endif
2388
2389 bool success = false;
2390 if (ConditionPassed(opcode)) {
2391 const addr_t sp = ReadCoreReg(SP_REG, &success);
2392 if (!success)
2393 return false;
2394
2395 uint32_t Rd;
2396 bool setflags;
2397 uint32_t imm32;
2398 switch (encoding) {
2399 case eEncodingT1:
2400 Rd = 13;
2401 setflags = false;
2402 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
2403 break;
2404 case eEncodingT2:
2405 Rd = Bits32(opcode, 11, 8);
2406 setflags = BitIsSet(opcode, 20);
2407 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2408 if (Rd == 15 && setflags)
2409 return EmulateCMPImm(opcode, eEncodingT2);
2410 if (Rd == 15 && !setflags)
2411 return false;
2412 break;
2413 case eEncodingT3:
2414 Rd = Bits32(opcode, 11, 8);
2415 setflags = false;
2416 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
2417 if (Rd == 15)
2418 return false;
2419 break;
2420 case eEncodingA1:
2421 Rd = Bits32(opcode, 15, 12);
2422 setflags = BitIsSet(opcode, 20);
2423 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2424
2425 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
2426 // instructions;
2427 if (Rd == 15 && setflags)
2428 return EmulateSUBSPcLrEtc(opcode, encoding);
2429 break;
2430 default:
2431 return false;
2432 }
2433 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
2434
2435 EmulateInstruction::Context context;
2436 if (Rd == 13) {
2437 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting
2438 // to negate it, or the wrong
2439 // value gets passed down to context.SetImmediateSigned.
2440 context.type = EmulateInstruction::eContextAdjustStackPointer;
2441 context.SetImmediateSigned(-imm64); // the stack pointer offset
2442 } else {
2443 context.type = EmulateInstruction::eContextImmediate;
2444 context.SetNoArgs();
2445 }
2446
2447 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
2448 res.carry_out, res.overflow))
2449 return false;
2450 }
2451 return true;
2452 }
2453
2454 // A store operation to the stack that also updates the SP.
EmulateSTRRtSP(const uint32_t opcode,const ARMEncoding encoding)2455 bool EmulateInstructionARM::EmulateSTRRtSP(const uint32_t opcode,
2456 const ARMEncoding encoding) {
2457 #if 0
2458 // ARM pseudo code...
2459 if (ConditionPassed())
2460 {
2461 EncodingSpecificOperations();
2462 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
2463 address = if index then offset_addr else R[n];
2464 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
2465 if wback then R[n] = offset_addr;
2466 }
2467 #endif
2468
2469 bool success = false;
2470 if (ConditionPassed(opcode)) {
2471 const uint32_t addr_byte_size = GetAddressByteSize();
2472 const addr_t sp = ReadCoreReg(SP_REG, &success);
2473 if (!success)
2474 return false;
2475 uint32_t Rt; // the source register
2476 uint32_t imm12;
2477 uint32_t
2478 Rn; // This function assumes Rn is the SP, but we should verify that.
2479
2480 bool index;
2481 bool add;
2482 bool wback;
2483 switch (encoding) {
2484 case eEncodingA1:
2485 Rt = Bits32(opcode, 15, 12);
2486 imm12 = Bits32(opcode, 11, 0);
2487 Rn = Bits32(opcode, 19, 16);
2488
2489 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
2490 return false;
2491
2492 index = BitIsSet(opcode, 24);
2493 add = BitIsSet(opcode, 23);
2494 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
2495
2496 if (wback && ((Rn == 15) || (Rn == Rt)))
2497 return false;
2498 break;
2499 default:
2500 return false;
2501 }
2502 addr_t offset_addr;
2503 if (add)
2504 offset_addr = sp + imm12;
2505 else
2506 offset_addr = sp - imm12;
2507
2508 addr_t addr;
2509 if (index)
2510 addr = offset_addr;
2511 else
2512 addr = sp;
2513
2514 EmulateInstruction::Context context;
2515 context.type = EmulateInstruction::eContextPushRegisterOnStack;
2516 RegisterInfo sp_reg;
2517 RegisterInfo dwarf_reg;
2518
2519 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
2520 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rt, dwarf_reg);
2521 context.SetRegisterToRegisterPlusOffset(dwarf_reg, sp_reg, addr - sp);
2522 if (Rt != 15) {
2523 uint32_t reg_value = ReadCoreReg(Rt, &success);
2524 if (!success)
2525 return false;
2526 if (!MemUWrite(context, addr, reg_value, addr_byte_size))
2527 return false;
2528 } else {
2529 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2530 if (!success)
2531 return false;
2532 if (!MemUWrite(context, addr, pc, addr_byte_size))
2533 return false;
2534 }
2535
2536 if (wback) {
2537 context.type = EmulateInstruction::eContextAdjustStackPointer;
2538 context.SetImmediateSigned(addr - sp);
2539 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2540 LLDB_REGNUM_GENERIC_SP, offset_addr))
2541 return false;
2542 }
2543 }
2544 return true;
2545 }
2546
2547 // Vector Push stores multiple extension registers to the stack. It also
2548 // updates SP to point to the start of the stored data.
EmulateVPUSH(const uint32_t opcode,const ARMEncoding encoding)2549 bool EmulateInstructionARM::EmulateVPUSH(const uint32_t opcode,
2550 const ARMEncoding encoding) {
2551 #if 0
2552 // ARM pseudo code...
2553 if (ConditionPassed())
2554 {
2555 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2556 address = SP - imm32;
2557 SP = SP - imm32;
2558 if single_regs then
2559 for r = 0 to regs-1
2560 MemA[address,4] = S[d+r]; address = address+4;
2561 else
2562 for r = 0 to regs-1
2563 // Store as two word-aligned words in the correct order for
2564 // current endianness.
2565 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
2566 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
2567 address = address+8;
2568 }
2569 #endif
2570
2571 bool success = false;
2572 if (ConditionPassed(opcode)) {
2573 const uint32_t addr_byte_size = GetAddressByteSize();
2574 const addr_t sp = ReadCoreReg(SP_REG, &success);
2575 if (!success)
2576 return false;
2577 bool single_regs;
2578 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2579 uint32_t imm32; // stack offset
2580 uint32_t regs; // number of registers
2581 switch (encoding) {
2582 case eEncodingT1:
2583 case eEncodingA1:
2584 single_regs = false;
2585 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
2586 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2587 // If UInt(imm8) is odd, see "FSTMX".
2588 regs = Bits32(opcode, 7, 0) / 2;
2589 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2590 if (regs == 0 || regs > 16 || (d + regs) > 32)
2591 return false;
2592 break;
2593 case eEncodingT2:
2594 case eEncodingA2:
2595 single_regs = true;
2596 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
2597 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2598 regs = Bits32(opcode, 7, 0);
2599 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2600 if (regs == 0 || regs > 16 || (d + regs) > 32)
2601 return false;
2602 break;
2603 default:
2604 return false;
2605 }
2606 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2607 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2608 addr_t sp_offset = imm32;
2609 addr_t addr = sp - sp_offset;
2610 uint32_t i;
2611
2612 EmulateInstruction::Context context;
2613 context.type = EmulateInstruction::eContextPushRegisterOnStack;
2614
2615 RegisterInfo dwarf_reg;
2616 RegisterInfo sp_reg;
2617 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
2618 for (i = 0; i < regs; ++i) {
2619 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
2620 context.SetRegisterToRegisterPlusOffset(dwarf_reg, sp_reg, addr - sp);
2621 // uint64_t to accommodate 64-bit registers.
2622 uint64_t reg_value = ReadRegisterUnsigned(&dwarf_reg, 0, &success);
2623 if (!success)
2624 return false;
2625 if (!MemAWrite(context, addr, reg_value, reg_byte_size))
2626 return false;
2627 addr += reg_byte_size;
2628 }
2629
2630 context.type = EmulateInstruction::eContextAdjustStackPointer;
2631 context.SetImmediateSigned(-sp_offset);
2632
2633 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2634 LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
2635 return false;
2636 }
2637 return true;
2638 }
2639
2640 // Vector Pop loads multiple extension registers from the stack. It also
2641 // updates SP to point just above the loaded data.
EmulateVPOP(const uint32_t opcode,const ARMEncoding encoding)2642 bool EmulateInstructionARM::EmulateVPOP(const uint32_t opcode,
2643 const ARMEncoding encoding) {
2644 #if 0
2645 // ARM pseudo code...
2646 if (ConditionPassed())
2647 {
2648 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2649 address = SP;
2650 SP = SP + imm32;
2651 if single_regs then
2652 for r = 0 to regs-1
2653 S[d+r] = MemA[address,4]; address = address+4;
2654 else
2655 for r = 0 to regs-1
2656 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
2657 // Combine the word-aligned words in the correct order for
2658 // current endianness.
2659 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
2660 }
2661 #endif
2662
2663 bool success = false;
2664 if (ConditionPassed(opcode)) {
2665 const uint32_t addr_byte_size = GetAddressByteSize();
2666 const addr_t sp = ReadCoreReg(SP_REG, &success);
2667 if (!success)
2668 return false;
2669 bool single_regs;
2670 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2671 uint32_t imm32; // stack offset
2672 uint32_t regs; // number of registers
2673 switch (encoding) {
2674 case eEncodingT1:
2675 case eEncodingA1:
2676 single_regs = false;
2677 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
2678 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2679 // If UInt(imm8) is odd, see "FLDMX".
2680 regs = Bits32(opcode, 7, 0) / 2;
2681 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2682 if (regs == 0 || regs > 16 || (d + regs) > 32)
2683 return false;
2684 break;
2685 case eEncodingT2:
2686 case eEncodingA2:
2687 single_regs = true;
2688 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
2689 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2690 regs = Bits32(opcode, 7, 0);
2691 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2692 if (regs == 0 || regs > 16 || (d + regs) > 32)
2693 return false;
2694 break;
2695 default:
2696 return false;
2697 }
2698 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2699 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2700 addr_t sp_offset = imm32;
2701 addr_t addr = sp;
2702 uint32_t i;
2703 uint64_t data; // uint64_t to accommodate 64-bit registers.
2704
2705 EmulateInstruction::Context context;
2706 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2707
2708 RegisterInfo dwarf_reg;
2709 RegisterInfo sp_reg;
2710 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
2711 for (i = 0; i < regs; ++i) {
2712 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
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
2722 context.type = EmulateInstruction::eContextAdjustStackPointer;
2723 context.SetImmediateSigned(sp_offset);
2724
2725 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2726 LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2727 return false;
2728 }
2729 return true;
2730 }
2731
2732 // SVC (previously SWI)
EmulateSVC(const uint32_t opcode,const ARMEncoding encoding)2733 bool 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
2768 EmulateInstruction::Context context;
2769 context.type = EmulateInstruction::eContextSupervisorCall;
2770 context.SetISAAndImmediate(mode, imm32);
2771 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2772 LLDB_REGNUM_GENERIC_RA, lr))
2773 return false;
2774 }
2775 return true;
2776 }
2777
2778 // If Then makes up to four following instructions (the IT block) conditional.
EmulateIT(const uint32_t opcode,const ARMEncoding encoding)2779 bool EmulateInstructionARM::EmulateIT(const uint32_t opcode,
2780 const ARMEncoding encoding) {
2781 #if 0
2782 // ARM pseudo code...
2783 EncodingSpecificOperations();
2784 ITSTATE.IT<7:0> = firstcond:mask;
2785 #endif
2786
2787 m_it_session.InitIT(Bits32(opcode, 7, 0));
2788 return true;
2789 }
2790
EmulateNop(const uint32_t opcode,const ARMEncoding encoding)2791 bool 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.
EmulateB(const uint32_t opcode,const ARMEncoding encoding)2798 bool EmulateInstructionARM::EmulateB(const uint32_t opcode,
2799 const ARMEncoding encoding) {
2800 #if 0
2801 // ARM pseudo code...
2802 if (ConditionPassed())
2803 {
2804 EncodingSpecificOperations();
2805 BranchWritePC(PC + imm32);
2806 }
2807 #endif
2808
2809 bool success = false;
2810
2811 if (ConditionPassed(opcode)) {
2812 EmulateInstruction::Context context;
2813 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2814 const uint32_t pc = ReadCoreReg(PC_REG, &success);
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
EmulateCB(const uint32_t opcode,const ARMEncoding encoding)2882 bool EmulateInstructionARM::EmulateCB(const uint32_t opcode,
2883 const ARMEncoding encoding) {
2884 #if 0
2885 // ARM pseudo code...
2886 EncodingSpecificOperations();
2887 if nonzero ^ IsZero(R[n]) then
2888 BranchWritePC(PC + imm32);
2889 #endif
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
2898 EmulateInstruction::Context context;
2899 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
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
EmulateTB(const uint32_t opcode,const ARMEncoding encoding)2936 bool EmulateInstructionARM::EmulateTB(const uint32_t opcode,
2937 const ARMEncoding encoding) {
2938 #if 0
2939 // ARM pseudo code...
2940 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2941 if is_tbh then
2942 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2943 else
2944 halfwords = UInt(MemU[R[n]+R[m], 1]);
2945 BranchWritePC(PC + 2*halfwords);
2946 #endif
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
2985 EmulateInstruction::Context context;
2986 context.type = EmulateInstruction::eContextTableBranchReadMemory;
2987 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
2988 if (!success)
2989 return false;
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;
2997 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
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.
EmulateADDImmThumb(const uint32_t opcode,const ARMEncoding encoding)3010 bool EmulateInstructionARM::EmulateADDImmThumb(const uint32_t opcode,
3011 const ARMEncoding encoding) {
3012 #if 0
3013 if ConditionPassed() then
3014 EncodingSpecificOperations();
3015 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3016 R[d] = result;
3017 if setflags then
3018 APSR.N = result<31>;
3019 APSR.Z = IsZeroBit(result);
3020 APSR.C = carry;
3021 APSR.V = overflow;
3022 #endif
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 =
3102 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
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 RegisterInfo reg_n;
3110 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, reg_n);
3111
3112 EmulateInstruction::Context context;
3113 context.type = eContextArithmetic;
3114 context.SetRegisterPlusOffset(reg_n, imm32);
3115
3116 // R[d] = result;
3117 // if setflags then
3118 // APSR.N = result<31>;
3119 // APSR.Z = IsZeroBit(result);
3120 // APSR.C = carry;
3121 // APSR.V = overflow;
3122 if (!WriteCoreRegOptionalFlags(context, res.result, d, setflags,
3123 res.carry_out, res.overflow))
3124 return false;
3125 }
3126 return true;
3127 }
3128
3129 // This instruction adds an immediate value to a register value, and writes the
3130 // result to the destination register. It can optionally update the condition
3131 // flags based on the result.
EmulateADDImmARM(const uint32_t opcode,const ARMEncoding encoding)3132 bool EmulateInstructionARM::EmulateADDImmARM(const uint32_t opcode,
3133 const ARMEncoding encoding) {
3134 #if 0
3135 // ARM pseudo code...
3136 if ConditionPassed() then
3137 EncodingSpecificOperations();
3138 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3139 if d == 15 then
3140 ALUWritePC(result); // setflags is always FALSE here
3141 else
3142 R[d] = result;
3143 if setflags then
3144 APSR.N = result<31>;
3145 APSR.Z = IsZeroBit(result);
3146 APSR.C = carry;
3147 APSR.V = overflow;
3148 #endif
3149
3150 bool success = false;
3151
3152 if (ConditionPassed(opcode)) {
3153 uint32_t Rd, Rn;
3154 uint32_t
3155 imm32; // the immediate value to be added to the value obtained from Rn
3156 bool setflags;
3157 switch (encoding) {
3158 case eEncodingA1:
3159 Rd = Bits32(opcode, 15, 12);
3160 Rn = Bits32(opcode, 19, 16);
3161 setflags = BitIsSet(opcode, 20);
3162 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3163 break;
3164 default:
3165 return false;
3166 }
3167
3168 // Read the first operand.
3169 uint32_t val1 = ReadCoreReg(Rn, &success);
3170 if (!success)
3171 return false;
3172
3173 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
3174
3175 EmulateInstruction::Context context;
3176 if (Rd == 13)
3177 context.type = EmulateInstruction::eContextAdjustStackPointer;
3178 else if (Rd == GetFramePointerRegisterNumber())
3179 context.type = EmulateInstruction::eContextSetFramePointer;
3180 else
3181 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3182
3183 RegisterInfo dwarf_reg;
3184 GetRegisterInfo(eRegisterKindDWARF, Rn, dwarf_reg);
3185 context.SetRegisterPlusOffset(dwarf_reg, imm32);
3186
3187 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
3188 res.carry_out, res.overflow))
3189 return false;
3190 }
3191 return true;
3192 }
3193
3194 // This instruction adds a register value and an optionally-shifted register
3195 // value, and writes the result to the destination register. It can optionally
3196 // update the condition flags based on the result.
EmulateADDReg(const uint32_t opcode,const ARMEncoding encoding)3197 bool EmulateInstructionARM::EmulateADDReg(const uint32_t opcode,
3198 const ARMEncoding encoding) {
3199 #if 0
3200 // ARM pseudo code...
3201 if ConditionPassed() then
3202 EncodingSpecificOperations();
3203 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
3204 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
3205 if d == 15 then
3206 ALUWritePC(result); // setflags is always FALSE here
3207 else
3208 R[d] = result;
3209 if setflags then
3210 APSR.N = result<31>;
3211 APSR.Z = IsZeroBit(result);
3212 APSR.C = carry;
3213 APSR.V = overflow;
3214 #endif
3215
3216 bool success = false;
3217
3218 if (ConditionPassed(opcode)) {
3219 uint32_t Rd, Rn, Rm;
3220 ARM_ShifterType shift_t;
3221 uint32_t shift_n; // the shift applied to the value read from Rm
3222 bool setflags;
3223 switch (encoding) {
3224 case eEncodingT1:
3225 Rd = Bits32(opcode, 2, 0);
3226 Rn = Bits32(opcode, 5, 3);
3227 Rm = Bits32(opcode, 8, 6);
3228 setflags = !InITBlock();
3229 shift_t = SRType_LSL;
3230 shift_n = 0;
3231 break;
3232 case eEncodingT2:
3233 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
3234 Rm = Bits32(opcode, 6, 3);
3235 setflags = false;
3236 shift_t = SRType_LSL;
3237 shift_n = 0;
3238 if (Rn == 15 && Rm == 15)
3239 return false;
3240 if (Rd == 15 && InITBlock() && !LastInITBlock())
3241 return false;
3242 break;
3243 case eEncodingA1:
3244 Rd = Bits32(opcode, 15, 12);
3245 Rn = Bits32(opcode, 19, 16);
3246 Rm = Bits32(opcode, 3, 0);
3247 setflags = BitIsSet(opcode, 20);
3248 shift_n = DecodeImmShiftARM(opcode, shift_t);
3249 break;
3250 default:
3251 return false;
3252 }
3253
3254 // Read the first operand.
3255 uint32_t val1 = ReadCoreReg(Rn, &success);
3256 if (!success)
3257 return false;
3258
3259 // Read the second operand.
3260 uint32_t val2 = ReadCoreReg(Rm, &success);
3261 if (!success)
3262 return false;
3263
3264 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
3265 if (!success)
3266 return false;
3267 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
3268
3269 EmulateInstruction::Context context;
3270 context.type = eContextArithmetic;
3271 RegisterInfo op1_reg;
3272 RegisterInfo op2_reg;
3273 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn, op1_reg);
3274 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, op2_reg);
3275 context.SetRegisterRegisterOperands(op1_reg, op2_reg);
3276
3277 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
3278 res.carry_out, res.overflow))
3279 return false;
3280 }
3281 return true;
3282 }
3283
3284 // Compare Negative (immediate) adds a register value and an immediate value.
3285 // It updates the condition flags based on the result, and discards the result.
EmulateCMNImm(const uint32_t opcode,const ARMEncoding encoding)3286 bool EmulateInstructionARM::EmulateCMNImm(const uint32_t opcode,
3287 const ARMEncoding encoding) {
3288 #if 0
3289 // ARM pseudo code...
3290 if ConditionPassed() then
3291 EncodingSpecificOperations();
3292 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3293 APSR.N = result<31>;
3294 APSR.Z = IsZeroBit(result);
3295 APSR.C = carry;
3296 APSR.V = overflow;
3297 #endif
3298
3299 bool success = false;
3300
3301 uint32_t Rn; // the first operand
3302 uint32_t imm32; // the immediate value to be compared with
3303 switch (encoding) {
3304 case eEncodingT1:
3305 Rn = Bits32(opcode, 19, 16);
3306 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
3307 if (Rn == 15)
3308 return false;
3309 break;
3310 case eEncodingA1:
3311 Rn = Bits32(opcode, 19, 16);
3312 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3313 break;
3314 default:
3315 return false;
3316 }
3317 // Read the register value from the operand register Rn.
3318 uint32_t reg_val = ReadCoreReg(Rn, &success);
3319 if (!success)
3320 return false;
3321
3322 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
3323
3324 EmulateInstruction::Context context;
3325 context.type = EmulateInstruction::eContextImmediate;
3326 context.SetNoArgs();
3327 return WriteFlags(context, res.result, res.carry_out, res.overflow);
3328 }
3329
3330 // Compare Negative (register) adds a register value and an optionally-shifted
3331 // register value. It updates the condition flags based on the result, and
3332 // discards the result.
EmulateCMNReg(const uint32_t opcode,const ARMEncoding encoding)3333 bool EmulateInstructionARM::EmulateCMNReg(const uint32_t opcode,
3334 const ARMEncoding encoding) {
3335 #if 0
3336 // ARM pseudo code...
3337 if ConditionPassed() then
3338 EncodingSpecificOperations();
3339 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
3340 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
3341 APSR.N = result<31>;
3342 APSR.Z = IsZeroBit(result);
3343 APSR.C = carry;
3344 APSR.V = overflow;
3345 #endif
3346
3347 bool success = false;
3348
3349 uint32_t Rn; // the first operand
3350 uint32_t Rm; // the second operand
3351 ARM_ShifterType shift_t;
3352 uint32_t shift_n; // the shift applied to the value read from Rm
3353 switch (encoding) {
3354 case eEncodingT1:
3355 Rn = Bits32(opcode, 2, 0);
3356 Rm = Bits32(opcode, 5, 3);
3357 shift_t = SRType_LSL;
3358 shift_n = 0;
3359 break;
3360 case eEncodingT2:
3361 Rn = Bits32(opcode, 19, 16);
3362 Rm = Bits32(opcode, 3, 0);
3363 shift_n = DecodeImmShiftThumb(opcode, shift_t);
3364 // if n == 15 || BadReg(m) then UNPREDICTABLE;
3365 if (Rn == 15 || BadReg(Rm))
3366 return false;
3367 break;
3368 case eEncodingA1:
3369 Rn = Bits32(opcode, 19, 16);
3370 Rm = Bits32(opcode, 3, 0);
3371 shift_n = DecodeImmShiftARM(opcode, shift_t);
3372 break;
3373 default:
3374 return false;
3375 }
3376 // Read the register value from register Rn.
3377 uint32_t val1 = ReadCoreReg(Rn, &success);
3378 if (!success)
3379 return false;
3380
3381 // Read the register value from register Rm.
3382 uint32_t val2 = ReadCoreReg(Rm, &success);
3383 if (!success)
3384 return false;
3385
3386 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
3387 if (!success)
3388 return false;
3389 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
3390
3391 EmulateInstruction::Context context;
3392 context.type = EmulateInstruction::eContextImmediate;
3393 context.SetNoArgs();
3394 return WriteFlags(context, res.result, res.carry_out, res.overflow);
3395 }
3396
3397 // Compare (immediate) subtracts an immediate value from a register value. It
3398 // updates the condition flags based on the result, and discards the result.
EmulateCMPImm(const uint32_t opcode,const ARMEncoding encoding)3399 bool EmulateInstructionARM::EmulateCMPImm(const uint32_t opcode,
3400 const ARMEncoding encoding) {
3401 #if 0
3402 // ARM pseudo code...
3403 if ConditionPassed() then
3404 EncodingSpecificOperations();
3405 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
3406 APSR.N = result<31>;
3407 APSR.Z = IsZeroBit(result);
3408 APSR.C = carry;
3409 APSR.V = overflow;
3410 #endif
3411
3412 bool success = false;
3413
3414 uint32_t Rn; // the first operand
3415 uint32_t imm32; // the immediate value to be compared with
3416 switch (encoding) {
3417 case eEncodingT1:
3418 Rn = Bits32(opcode, 10, 8);
3419 imm32 = Bits32(opcode, 7, 0);
3420 break;
3421 case eEncodingT2:
3422 Rn = Bits32(opcode, 19, 16);
3423 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
3424 if (Rn == 15)
3425 return false;
3426 break;
3427 case eEncodingA1:
3428 Rn = Bits32(opcode, 19, 16);
3429 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3430 break;
3431 default:
3432 return false;
3433 }
3434 // Read the register value from the operand register Rn.
3435 uint32_t reg_val = ReadCoreReg(Rn, &success);
3436 if (!success)
3437 return false;
3438
3439 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
3440
3441 EmulateInstruction::Context context;
3442 context.type = EmulateInstruction::eContextImmediate;
3443 context.SetNoArgs();
3444 return WriteFlags(context, res.result, res.carry_out, res.overflow);
3445 }
3446
3447 // Compare (register) subtracts an optionally-shifted register value from a
3448 // register value. It updates the condition flags based on the result, and
3449 // discards the result.
EmulateCMPReg(const uint32_t opcode,const ARMEncoding encoding)3450 bool EmulateInstructionARM::EmulateCMPReg(const uint32_t opcode,
3451 const ARMEncoding encoding) {
3452 #if 0
3453 // ARM pseudo code...
3454 if ConditionPassed() then
3455 EncodingSpecificOperations();
3456 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
3457 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
3458 APSR.N = result<31>;
3459 APSR.Z = IsZeroBit(result);
3460 APSR.C = carry;
3461 APSR.V = overflow;
3462 #endif
3463
3464 bool success = false;
3465
3466 uint32_t Rn; // the first operand
3467 uint32_t Rm; // the second operand
3468 ARM_ShifterType shift_t;
3469 uint32_t shift_n; // the shift applied to the value read from Rm
3470 switch (encoding) {
3471 case eEncodingT1:
3472 Rn = Bits32(opcode, 2, 0);
3473 Rm = Bits32(opcode, 5, 3);
3474 shift_t = SRType_LSL;
3475 shift_n = 0;
3476 break;
3477 case eEncodingT2:
3478 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
3479 Rm = Bits32(opcode, 6, 3);
3480 shift_t = SRType_LSL;
3481 shift_n = 0;
3482 if (Rn < 8 && Rm < 8)
3483 return false;
3484 if (Rn == 15 || Rm == 15)
3485 return false;
3486 break;
3487 case eEncodingT3:
3488 Rn = Bits32(opcode, 19, 16);
3489 Rm = Bits32(opcode, 3, 0);
3490 shift_n = DecodeImmShiftThumb(opcode, shift_t);
3491 if (Rn == 15 || BadReg(Rm))
3492 return false;
3493 break;
3494 case eEncodingA1:
3495 Rn = Bits32(opcode, 19, 16);
3496 Rm = Bits32(opcode, 3, 0);
3497 shift_n = DecodeImmShiftARM(opcode, shift_t);
3498 break;
3499 default:
3500 return false;
3501 }
3502 // Read the register value from register Rn.
3503 uint32_t val1 = ReadCoreReg(Rn, &success);
3504 if (!success)
3505 return false;
3506
3507 // Read the register value from register Rm.
3508 uint32_t val2 = ReadCoreReg(Rm, &success);
3509 if (!success)
3510 return false;
3511
3512 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
3513 if (!success)
3514 return false;
3515 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
3516
3517 EmulateInstruction::Context context;
3518 context.type = EmulateInstruction::eContextImmediate;
3519 context.SetNoArgs();
3520 return WriteFlags(context, res.result, res.carry_out, res.overflow);
3521 }
3522
3523 // Arithmetic Shift Right (immediate) shifts a register value right by an
3524 // immediate number of bits, shifting in copies of its sign bit, and writes the
3525 // result to the destination register. It can optionally update the condition
3526 // flags based on the result.
EmulateASRImm(const uint32_t opcode,const ARMEncoding encoding)3527 bool EmulateInstructionARM::EmulateASRImm(const uint32_t opcode,
3528 const ARMEncoding encoding) {
3529 #if 0
3530 // ARM pseudo code...
3531 if ConditionPassed() then
3532 EncodingSpecificOperations();
3533 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
3534 if d == 15 then // Can only occur for ARM encoding
3535 ALUWritePC(result); // setflags is always FALSE here
3536 else
3537 R[d] = result;
3538 if setflags then
3539 APSR.N = result<31>;
3540 APSR.Z = IsZeroBit(result);
3541 APSR.C = carry;
3542 // APSR.V unchanged
3543 #endif
3544
3545 return EmulateShiftImm(opcode, encoding, SRType_ASR);
3546 }
3547
3548 // Arithmetic Shift Right (register) shifts a register value right by a
3549 // variable number of bits, shifting in copies of its sign bit, and writes the
3550 // result to the destination register. The variable number of bits is read from
3551 // the bottom byte of a register. It can optionally update the condition flags
3552 // based on the result.
EmulateASRReg(const uint32_t opcode,const ARMEncoding encoding)3553 bool EmulateInstructionARM::EmulateASRReg(const uint32_t opcode,
3554 const ARMEncoding encoding) {
3555 #if 0
3556 // ARM pseudo code...
3557 if ConditionPassed() then
3558 EncodingSpecificOperations();
3559 shift_n = UInt(R[m]<7:0>);
3560 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
3561 R[d] = result;
3562 if setflags then
3563 APSR.N = result<31>;
3564 APSR.Z = IsZeroBit(result);
3565 APSR.C = carry;
3566 // APSR.V unchanged
3567 #endif
3568
3569 return EmulateShiftReg(opcode, encoding, SRType_ASR);
3570 }
3571
3572 // Logical Shift Left (immediate) shifts a register value left by an immediate
3573 // number of bits, shifting in zeros, and writes the result to the destination
3574 // register. It can optionally update the condition flags based on the result.
EmulateLSLImm(const uint32_t opcode,const ARMEncoding encoding)3575 bool EmulateInstructionARM::EmulateLSLImm(const uint32_t opcode,
3576 const ARMEncoding encoding) {
3577 #if 0
3578 // ARM pseudo code...
3579 if ConditionPassed() then
3580 EncodingSpecificOperations();
3581 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
3582 if d == 15 then // Can only occur for ARM encoding
3583 ALUWritePC(result); // setflags is always FALSE here
3584 else
3585 R[d] = result;
3586 if setflags then
3587 APSR.N = result<31>;
3588 APSR.Z = IsZeroBit(result);
3589 APSR.C = carry;
3590 // APSR.V unchanged
3591 #endif
3592
3593 return EmulateShiftImm(opcode, encoding, SRType_LSL);
3594 }
3595
3596 // Logical Shift Left (register) shifts a register value left by a variable
3597 // number of bits, shifting in zeros, and writes the result to the destination
3598 // register. The variable number of bits is read from the bottom byte of a
3599 // register. It can optionally update the condition flags based on the result.
EmulateLSLReg(const uint32_t opcode,const ARMEncoding encoding)3600 bool EmulateInstructionARM::EmulateLSLReg(const uint32_t opcode,
3601 const ARMEncoding encoding) {
3602 #if 0
3603 // ARM pseudo code...
3604 if ConditionPassed() then
3605 EncodingSpecificOperations();
3606 shift_n = UInt(R[m]<7:0>);
3607 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
3608 R[d] = result;
3609 if setflags then
3610 APSR.N = result<31>;
3611 APSR.Z = IsZeroBit(result);
3612 APSR.C = carry;
3613 // APSR.V unchanged
3614 #endif
3615
3616 return EmulateShiftReg(opcode, encoding, SRType_LSL);
3617 }
3618
3619 // Logical Shift Right (immediate) shifts a register value right by an
3620 // immediate number of bits, shifting in zeros, and writes the result to the
3621 // destination register. It can optionally update the condition flags based on
3622 // the result.
EmulateLSRImm(const uint32_t opcode,const ARMEncoding encoding)3623 bool EmulateInstructionARM::EmulateLSRImm(const uint32_t opcode,
3624 const ARMEncoding encoding) {
3625 #if 0
3626 // ARM pseudo code...
3627 if ConditionPassed() then
3628 EncodingSpecificOperations();
3629 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3630 if d == 15 then // Can only occur for ARM encoding
3631 ALUWritePC(result); // setflags is always FALSE here
3632 else
3633 R[d] = result;
3634 if setflags then
3635 APSR.N = result<31>;
3636 APSR.Z = IsZeroBit(result);
3637 APSR.C = carry;
3638 // APSR.V unchanged
3639 #endif
3640
3641 return EmulateShiftImm(opcode, encoding, SRType_LSR);
3642 }
3643
3644 // Logical Shift Right (register) shifts a register value right by a variable
3645 // number of bits, shifting in zeros, and writes the result to the destination
3646 // register. The variable number of bits is read from the bottom byte of a
3647 // register. It can optionally update the condition flags based on the result.
EmulateLSRReg(const uint32_t opcode,const ARMEncoding encoding)3648 bool EmulateInstructionARM::EmulateLSRReg(const uint32_t opcode,
3649 const ARMEncoding encoding) {
3650 #if 0
3651 // ARM pseudo code...
3652 if ConditionPassed() then
3653 EncodingSpecificOperations();
3654 shift_n = UInt(R[m]<7:0>);
3655 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3656 R[d] = result;
3657 if setflags then
3658 APSR.N = result<31>;
3659 APSR.Z = IsZeroBit(result);
3660 APSR.C = carry;
3661 // APSR.V unchanged
3662 #endif
3663
3664 return EmulateShiftReg(opcode, encoding, SRType_LSR);
3665 }
3666
3667 // Rotate Right (immediate) provides the value of the contents of a register
3668 // rotated by a constant value. The bits that are rotated off the right end are
3669 // inserted into the vacated bit positions on the left. It can optionally
3670 // update the condition flags based on the result.
EmulateRORImm(const uint32_t opcode,const ARMEncoding encoding)3671 bool EmulateInstructionARM::EmulateRORImm(const uint32_t opcode,
3672 const ARMEncoding encoding) {
3673 #if 0
3674 // ARM pseudo code...
3675 if ConditionPassed() then
3676 EncodingSpecificOperations();
3677 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3678 if d == 15 then // Can only occur for ARM encoding
3679 ALUWritePC(result); // setflags is always FALSE here
3680 else
3681 R[d] = result;
3682 if setflags then
3683 APSR.N = result<31>;
3684 APSR.Z = IsZeroBit(result);
3685 APSR.C = carry;
3686 // APSR.V unchanged
3687 #endif
3688
3689 return EmulateShiftImm(opcode, encoding, SRType_ROR);
3690 }
3691
3692 // Rotate Right (register) provides the value of the contents of a register
3693 // rotated by a variable number of bits. The bits that are rotated off the
3694 // right end are inserted into the vacated bit positions on the left. The
3695 // variable number of bits is read from the bottom byte of a register. It can
3696 // optionally update the condition flags based on the result.
EmulateRORReg(const uint32_t opcode,const ARMEncoding encoding)3697 bool EmulateInstructionARM::EmulateRORReg(const uint32_t opcode,
3698 const ARMEncoding encoding) {
3699 #if 0
3700 // ARM pseudo code...
3701 if ConditionPassed() then
3702 EncodingSpecificOperations();
3703 shift_n = UInt(R[m]<7:0>);
3704 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3705 R[d] = result;
3706 if setflags then
3707 APSR.N = result<31>;
3708 APSR.Z = IsZeroBit(result);
3709 APSR.C = carry;
3710 // APSR.V unchanged
3711 #endif
3712
3713 return EmulateShiftReg(opcode, encoding, SRType_ROR);
3714 }
3715
3716 // Rotate Right with Extend provides the value of the contents of a register
3717 // shifted right by one place, with the carry flag shifted into bit [31].
3718 //
3719 // RRX can optionally update the condition flags based on the result.
3720 // In that case, bit [0] is shifted into the carry flag.
EmulateRRX(const uint32_t opcode,const ARMEncoding encoding)3721 bool EmulateInstructionARM::EmulateRRX(const uint32_t opcode,
3722 const ARMEncoding encoding) {
3723 #if 0
3724 // ARM pseudo code...
3725 if ConditionPassed() then
3726 EncodingSpecificOperations();
3727 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3728 if d == 15 then // Can only occur for ARM encoding
3729 ALUWritePC(result); // setflags is always FALSE here
3730 else
3731 R[d] = result;
3732 if setflags then
3733 APSR.N = result<31>;
3734 APSR.Z = IsZeroBit(result);
3735 APSR.C = carry;
3736 // APSR.V unchanged
3737 #endif
3738
3739 return EmulateShiftImm(opcode, encoding, SRType_RRX);
3740 }
3741
EmulateShiftImm(const uint32_t opcode,const ARMEncoding encoding,ARM_ShifterType shift_type)3742 bool EmulateInstructionARM::EmulateShiftImm(const uint32_t opcode,
3743 const ARMEncoding encoding,
3744 ARM_ShifterType shift_type) {
3745 // assert(shift_type == SRType_ASR
3746 // || shift_type == SRType_LSL
3747 // || shift_type == SRType_LSR
3748 // || shift_type == SRType_ROR
3749 // || shift_type == SRType_RRX);
3750
3751 bool success = false;
3752
3753 if (ConditionPassed(opcode)) {
3754 uint32_t Rd; // the destination register
3755 uint32_t Rm; // the first operand register
3756 uint32_t imm5; // encoding for the shift amount
3757 uint32_t carry; // the carry bit after the shift operation
3758 bool setflags;
3759
3760 // Special case handling!
3761 // A8.6.139 ROR (immediate) -- Encoding T1
3762 ARMEncoding use_encoding = encoding;
3763 if (shift_type == SRType_ROR && use_encoding == eEncodingT1) {
3764 // Morph the T1 encoding from the ARM Architecture Manual into T2
3765 // encoding to have the same decoding of bit fields as the other Thumb2
3766 // shift operations.
3767 use_encoding = eEncodingT2;
3768 }
3769
3770 switch (use_encoding) {
3771 case eEncodingT1:
3772 // Due to the above special case handling!
3773 if (shift_type == SRType_ROR)
3774 return false;
3775
3776 Rd = Bits32(opcode, 2, 0);
3777 Rm = Bits32(opcode, 5, 3);
3778 setflags = !InITBlock();
3779 imm5 = Bits32(opcode, 10, 6);
3780 break;
3781 case eEncodingT2:
3782 // A8.6.141 RRX
3783 // There's no imm form of RRX instructions.
3784 if (shift_type == SRType_RRX)
3785 return false;
3786
3787 Rd = Bits32(opcode, 11, 8);
3788 Rm = Bits32(opcode, 3, 0);
3789 setflags = BitIsSet(opcode, 20);
3790 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3791 if (BadReg(Rd) || BadReg(Rm))
3792 return false;
3793 break;
3794 case eEncodingA1:
3795 Rd = Bits32(opcode, 15, 12);
3796 Rm = Bits32(opcode, 3, 0);
3797 setflags = BitIsSet(opcode, 20);
3798 imm5 = Bits32(opcode, 11, 7);
3799 break;
3800 default:
3801 return false;
3802 }
3803
3804 // A8.6.139 ROR (immediate)
3805 if (shift_type == SRType_ROR && imm5 == 0)
3806 shift_type = SRType_RRX;
3807
3808 // Get the first operand.
3809 uint32_t value = ReadCoreReg(Rm, &success);
3810 if (!success)
3811 return false;
3812
3813 // Decode the shift amount if not RRX.
3814 uint32_t amt =
3815 (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
3816
3817 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3818 if (!success)
3819 return false;
3820
3821 // The context specifies that an immediate is to be moved into Rd.
3822 EmulateInstruction::Context context;
3823 context.type = EmulateInstruction::eContextImmediate;
3824 context.SetNoArgs();
3825
3826 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3827 return false;
3828 }
3829 return true;
3830 }
3831
EmulateShiftReg(const uint32_t opcode,const ARMEncoding encoding,ARM_ShifterType shift_type)3832 bool EmulateInstructionARM::EmulateShiftReg(const uint32_t opcode,
3833 const ARMEncoding encoding,
3834 ARM_ShifterType shift_type) {
3835 // assert(shift_type == SRType_ASR
3836 // || shift_type == SRType_LSL
3837 // || shift_type == SRType_LSR
3838 // || shift_type == SRType_ROR);
3839
3840 bool success = false;
3841
3842 if (ConditionPassed(opcode)) {
3843 uint32_t Rd; // the destination register
3844 uint32_t Rn; // the first operand register
3845 uint32_t
3846 Rm; // the register whose bottom byte contains the amount to shift by
3847 uint32_t carry; // the carry bit after the shift operation
3848 bool setflags;
3849 switch (encoding) {
3850 case eEncodingT1:
3851 Rd = Bits32(opcode, 2, 0);
3852 Rn = Rd;
3853 Rm = Bits32(opcode, 5, 3);
3854 setflags = !InITBlock();
3855 break;
3856 case eEncodingT2:
3857 Rd = Bits32(opcode, 11, 8);
3858 Rn = Bits32(opcode, 19, 16);
3859 Rm = Bits32(opcode, 3, 0);
3860 setflags = BitIsSet(opcode, 20);
3861 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3862 return false;
3863 break;
3864 case eEncodingA1:
3865 Rd = Bits32(opcode, 15, 12);
3866 Rn = Bits32(opcode, 3, 0);
3867 Rm = Bits32(opcode, 11, 8);
3868 setflags = BitIsSet(opcode, 20);
3869 if (Rd == 15 || Rn == 15 || Rm == 15)
3870 return false;
3871 break;
3872 default:
3873 return false;
3874 }
3875
3876 // Get the first operand.
3877 uint32_t value = ReadCoreReg(Rn, &success);
3878 if (!success)
3879 return false;
3880 // Get the Rm register content.
3881 uint32_t val = ReadCoreReg(Rm, &success);
3882 if (!success)
3883 return false;
3884
3885 // Get the shift amount.
3886 uint32_t amt = Bits32(val, 7, 0);
3887
3888 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3889 if (!success)
3890 return false;
3891
3892 // The context specifies that an immediate is to be moved into Rd.
3893 EmulateInstruction::Context context;
3894 context.type = EmulateInstruction::eContextImmediate;
3895 context.SetNoArgs();
3896
3897 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3898 return false;
3899 }
3900 return true;
3901 }
3902
3903 // LDM loads multiple registers from consecutive memory locations, using an
3904 // address from a base register. Optionally the address just above the highest
3905 // of those locations can be written back to the base register.
EmulateLDM(const uint32_t opcode,const ARMEncoding encoding)3906 bool EmulateInstructionARM::EmulateLDM(const uint32_t opcode,
3907 const ARMEncoding encoding) {
3908 #if 0
3909 // ARM pseudo code...
3910 if ConditionPassed()
3911 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3912 address = R[n];
3913
3914 for i = 0 to 14
3915 if registers<i> == '1' then
3916 R[i] = MemA[address, 4]; address = address + 4;
3917 if registers<15> == '1' then
3918 LoadWritePC (MemA[address, 4]);
3919
3920 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3921 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3922
3923 #endif
3924
3925 bool success = false;
3926 if (ConditionPassed(opcode)) {
3927 uint32_t n;
3928 uint32_t registers = 0;
3929 bool wback;
3930 const uint32_t addr_byte_size = GetAddressByteSize();
3931 switch (encoding) {
3932 case eEncodingT1:
3933 // n = UInt(Rn); registers = '00000000':register_list; wback =
3934 // (registers<n> == '0');
3935 n = Bits32(opcode, 10, 8);
3936 registers = Bits32(opcode, 7, 0);
3937 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
3938 wback = BitIsClear(registers, n);
3939 // if BitCount(registers) < 1 then UNPREDICTABLE;
3940 if (BitCount(registers) < 1)
3941 return false;
3942 break;
3943 case eEncodingT2:
3944 // if W == '1' && Rn == '1101' then SEE POP;
3945 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
3946 n = Bits32(opcode, 19, 16);
3947 registers = Bits32(opcode, 15, 0);
3948 registers = registers & 0xdfff; // Make sure bit 13 is zero.
3949 wback = BitIsSet(opcode, 21);
3950
3951 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then
3952 // UNPREDICTABLE;
3953 if ((n == 15) || (BitCount(registers) < 2) ||
3954 (BitIsSet(opcode, 14) && BitIsSet(opcode, 15)))
3955 return false;
3956
3957 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
3958 // UNPREDICTABLE;
3959 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
3960 return false;
3961
3962 // if wback && registers<n> == '1' then UNPREDICTABLE;
3963 if (wback && BitIsSet(registers, n))
3964 return false;
3965 break;
3966
3967 case eEncodingA1:
3968 n = Bits32(opcode, 19, 16);
3969 registers = Bits32(opcode, 15, 0);
3970 wback = BitIsSet(opcode, 21);
3971 if ((n == 15) || (BitCount(registers) < 1))
3972 return false;
3973 break;
3974 default:
3975 return false;
3976 }
3977
3978 int32_t offset = 0;
3979 const addr_t base_address =
3980 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3981 if (!success)
3982 return false;
3983
3984 EmulateInstruction::Context context;
3985 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3986 RegisterInfo dwarf_reg;
3987 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
3988 context.SetRegisterPlusOffset(dwarf_reg, offset);
3989
3990 for (int i = 0; i < 14; ++i) {
3991 if (BitIsSet(registers, i)) {
3992 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3993 context.SetRegisterPlusOffset(dwarf_reg, offset);
3994 if (wback && (n == 13)) // Pop Instruction
3995 {
3996 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3997 context.SetAddress(base_address + offset);
3998 }
3999
4000 // R[i] = MemA [address, 4]; address = address + 4;
4001 uint32_t data = MemARead(context, base_address + offset, addr_byte_size,
4002 0, &success);
4003 if (!success)
4004 return false;
4005
4006 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4007 data))
4008 return false;
4009
4010 offset += addr_byte_size;
4011 }
4012 }
4013
4014 if (BitIsSet(registers, 15)) {
4015 // LoadWritePC (MemA [address, 4]);
4016 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4017 context.SetRegisterPlusOffset(dwarf_reg, offset);
4018 uint32_t data =
4019 MemARead(context, base_address + offset, addr_byte_size, 0, &success);
4020 if (!success)
4021 return false;
4022 // In ARMv5T and above, this is an interworking branch.
4023 if (!LoadWritePC(context, data))
4024 return false;
4025 }
4026
4027 if (wback && BitIsClear(registers, n)) {
4028 // R[n] = R[n] + 4 * BitCount (registers)
4029 int32_t offset = addr_byte_size * BitCount(registers);
4030 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4031 context.SetRegisterPlusOffset(dwarf_reg, offset);
4032
4033 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4034 base_address + offset))
4035 return false;
4036 }
4037 if (wback && BitIsSet(registers, n))
4038 // R[n] bits(32) UNKNOWN;
4039 return WriteBits32Unknown(n);
4040 }
4041 return true;
4042 }
4043
4044 // LDMDA loads multiple registers from consecutive memory locations using an
4045 // address from a base register.
4046 // The consecutive memory locations end at this address and the address just
4047 // below the lowest of those locations can optionally be written back to the
4048 // base register.
EmulateLDMDA(const uint32_t opcode,const ARMEncoding encoding)4049 bool EmulateInstructionARM::EmulateLDMDA(const uint32_t opcode,
4050 const ARMEncoding encoding) {
4051 #if 0
4052 // ARM pseudo code...
4053 if ConditionPassed() then
4054 EncodingSpecificOperations();
4055 address = R[n] - 4*BitCount(registers) + 4;
4056
4057 for i = 0 to 14
4058 if registers<i> == '1' then
4059 R[i] = MemA[address,4]; address = address + 4;
4060
4061 if registers<15> == '1' then
4062 LoadWritePC(MemA[address,4]);
4063
4064 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4065 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4066 #endif
4067
4068 bool success = false;
4069
4070 if (ConditionPassed(opcode)) {
4071 uint32_t n;
4072 uint32_t registers = 0;
4073 bool wback;
4074 const uint32_t addr_byte_size = GetAddressByteSize();
4075
4076 // EncodingSpecificOperations();
4077 switch (encoding) {
4078 case eEncodingA1:
4079 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4080 n = Bits32(opcode, 19, 16);
4081 registers = Bits32(opcode, 15, 0);
4082 wback = BitIsSet(opcode, 21);
4083
4084 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4085 if ((n == 15) || (BitCount(registers) < 1))
4086 return false;
4087
4088 break;
4089
4090 default:
4091 return false;
4092 }
4093 // address = R[n] - 4*BitCount(registers) + 4;
4094
4095 int32_t offset = 0;
4096 addr_t Rn = ReadCoreReg(n, &success);
4097
4098 if (!success)
4099 return false;
4100
4101 addr_t address =
4102 Rn - (addr_byte_size * BitCount(registers)) + addr_byte_size;
4103
4104 EmulateInstruction::Context context;
4105 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4106 RegisterInfo dwarf_reg;
4107 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
4108 context.SetRegisterPlusOffset(dwarf_reg, offset);
4109
4110 // for i = 0 to 14
4111 for (int i = 0; i < 14; ++i) {
4112 // if registers<i> == '1' then
4113 if (BitIsSet(registers, i)) {
4114 // R[i] = MemA[address,4]; address = address + 4;
4115 context.SetRegisterPlusOffset(dwarf_reg, Rn - (address + offset));
4116 uint32_t data =
4117 MemARead(context, address + offset, addr_byte_size, 0, &success);
4118 if (!success)
4119 return false;
4120 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4121 data))
4122 return false;
4123 offset += addr_byte_size;
4124 }
4125 }
4126
4127 // if registers<15> == '1' then
4128 // LoadWritePC(MemA[address,4]);
4129 if (BitIsSet(registers, 15)) {
4130 context.SetRegisterPlusOffset(dwarf_reg, offset);
4131 uint32_t data =
4132 MemARead(context, address + offset, addr_byte_size, 0, &success);
4133 if (!success)
4134 return false;
4135 // In ARMv5T and above, this is an interworking branch.
4136 if (!LoadWritePC(context, data))
4137 return false;
4138 }
4139
4140 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4141 if (wback && BitIsClear(registers, n)) {
4142 if (!success)
4143 return false;
4144
4145 offset = (addr_byte_size * BitCount(registers)) * -1;
4146 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4147 context.SetImmediateSigned(offset);
4148 addr_t addr = Rn + offset;
4149 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4150 addr))
4151 return false;
4152 }
4153
4154 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4155 if (wback && BitIsSet(registers, n))
4156 return WriteBits32Unknown(n);
4157 }
4158 return true;
4159 }
4160
4161 // LDMDB loads multiple registers from consecutive memory locations using an
4162 // address from a base register. The
4163 // consecutive memory locations end just below this address, and the address of
4164 // the lowest of those locations can be optionally written back to the base
4165 // register.
EmulateLDMDB(const uint32_t opcode,const ARMEncoding encoding)4166 bool EmulateInstructionARM::EmulateLDMDB(const uint32_t opcode,
4167 const ARMEncoding encoding) {
4168 #if 0
4169 // ARM pseudo code...
4170 if ConditionPassed() then
4171 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4172 address = R[n] - 4*BitCount(registers);
4173
4174 for i = 0 to 14
4175 if registers<i> == '1' then
4176 R[i] = MemA[address,4]; address = address + 4;
4177 if registers<15> == '1' then
4178 LoadWritePC(MemA[address,4]);
4179
4180 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4181 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
4182 #endif
4183
4184 bool success = false;
4185
4186 if (ConditionPassed(opcode)) {
4187 uint32_t n;
4188 uint32_t registers = 0;
4189 bool wback;
4190 const uint32_t addr_byte_size = GetAddressByteSize();
4191 switch (encoding) {
4192 case eEncodingT1:
4193 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
4194 n = Bits32(opcode, 19, 16);
4195 registers = Bits32(opcode, 15, 0);
4196 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
4197 wback = BitIsSet(opcode, 21);
4198
4199 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then
4200 // UNPREDICTABLE;
4201 if ((n == 15) || (BitCount(registers) < 2) ||
4202 (BitIsSet(opcode, 14) && BitIsSet(opcode, 15)))
4203 return false;
4204
4205 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
4206 // UNPREDICTABLE;
4207 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
4208 return false;
4209
4210 // if wback && registers<n> == '1' then UNPREDICTABLE;
4211 if (wback && BitIsSet(registers, n))
4212 return false;
4213
4214 break;
4215
4216 case eEncodingA1:
4217 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4218 n = Bits32(opcode, 19, 16);
4219 registers = Bits32(opcode, 15, 0);
4220 wback = BitIsSet(opcode, 21);
4221
4222 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4223 if ((n == 15) || (BitCount(registers) < 1))
4224 return false;
4225
4226 break;
4227
4228 default:
4229 return false;
4230 }
4231
4232 // address = R[n] - 4*BitCount(registers);
4233
4234 int32_t offset = 0;
4235 addr_t Rn =
4236 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4237
4238 if (!success)
4239 return false;
4240
4241 addr_t address = Rn - (addr_byte_size * BitCount(registers));
4242 EmulateInstruction::Context context;
4243 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4244 RegisterInfo dwarf_reg;
4245 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
4246 context.SetRegisterPlusOffset(dwarf_reg, Rn - address);
4247
4248 for (int i = 0; i < 14; ++i) {
4249 if (BitIsSet(registers, i)) {
4250 // R[i] = MemA[address,4]; address = address + 4;
4251 context.SetRegisterPlusOffset(dwarf_reg, Rn - (address + offset));
4252 uint32_t data =
4253 MemARead(context, address + offset, addr_byte_size, 0, &success);
4254 if (!success)
4255 return false;
4256
4257 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4258 data))
4259 return false;
4260
4261 offset += addr_byte_size;
4262 }
4263 }
4264
4265 // if registers<15> == '1' then
4266 // LoadWritePC(MemA[address,4]);
4267 if (BitIsSet(registers, 15)) {
4268 context.SetRegisterPlusOffset(dwarf_reg, offset);
4269 uint32_t data =
4270 MemARead(context, address + offset, addr_byte_size, 0, &success);
4271 if (!success)
4272 return false;
4273 // In ARMv5T and above, this is an interworking branch.
4274 if (!LoadWritePC(context, data))
4275 return false;
4276 }
4277
4278 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4279 if (wback && BitIsClear(registers, n)) {
4280 if (!success)
4281 return false;
4282
4283 offset = (addr_byte_size * BitCount(registers)) * -1;
4284 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4285 context.SetImmediateSigned(offset);
4286 addr_t addr = Rn + offset;
4287 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4288 addr))
4289 return false;
4290 }
4291
4292 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only
4293 // possible for encoding A1
4294 if (wback && BitIsSet(registers, n))
4295 return WriteBits32Unknown(n);
4296 }
4297 return true;
4298 }
4299
4300 // LDMIB loads multiple registers from consecutive memory locations using an
4301 // address from a base register. The
4302 // consecutive memory locations start just above this address, and thea ddress
4303 // of the last of those locations can optinoally be written back to the base
4304 // register.
EmulateLDMIB(const uint32_t opcode,const ARMEncoding encoding)4305 bool EmulateInstructionARM::EmulateLDMIB(const uint32_t opcode,
4306 const ARMEncoding encoding) {
4307 #if 0
4308 if ConditionPassed() then
4309 EncodingSpecificOperations();
4310 address = R[n] + 4;
4311
4312 for i = 0 to 14
4313 if registers<i> == '1' then
4314 R[i] = MemA[address,4]; address = address + 4;
4315 if registers<15> == '1' then
4316 LoadWritePC(MemA[address,4]);
4317
4318 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
4319 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4320 #endif
4321
4322 bool success = false;
4323
4324 if (ConditionPassed(opcode)) {
4325 uint32_t n;
4326 uint32_t registers = 0;
4327 bool wback;
4328 const uint32_t addr_byte_size = GetAddressByteSize();
4329 switch (encoding) {
4330 case eEncodingA1:
4331 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4332 n = Bits32(opcode, 19, 16);
4333 registers = Bits32(opcode, 15, 0);
4334 wback = BitIsSet(opcode, 21);
4335
4336 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4337 if ((n == 15) || (BitCount(registers) < 1))
4338 return false;
4339
4340 break;
4341 default:
4342 return false;
4343 }
4344 // address = R[n] + 4;
4345
4346 int32_t offset = 0;
4347 addr_t Rn =
4348 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4349
4350 if (!success)
4351 return false;
4352
4353 addr_t address = Rn + addr_byte_size;
4354
4355 EmulateInstruction::Context context;
4356 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4357 RegisterInfo dwarf_reg;
4358 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
4359 context.SetRegisterPlusOffset(dwarf_reg, offset);
4360
4361 for (int i = 0; i < 14; ++i) {
4362 if (BitIsSet(registers, i)) {
4363 // R[i] = MemA[address,4]; address = address + 4;
4364
4365 context.SetRegisterPlusOffset(dwarf_reg, offset + addr_byte_size);
4366 uint32_t data =
4367 MemARead(context, address + offset, addr_byte_size, 0, &success);
4368 if (!success)
4369 return false;
4370
4371 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4372 data))
4373 return false;
4374
4375 offset += addr_byte_size;
4376 }
4377 }
4378
4379 // if registers<15> == '1' then
4380 // LoadWritePC(MemA[address,4]);
4381 if (BitIsSet(registers, 15)) {
4382 context.SetRegisterPlusOffset(dwarf_reg, offset);
4383 uint32_t data =
4384 MemARead(context, address + offset, addr_byte_size, 0, &success);
4385 if (!success)
4386 return false;
4387 // In ARMv5T and above, this is an interworking branch.
4388 if (!LoadWritePC(context, data))
4389 return false;
4390 }
4391
4392 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
4393 if (wback && BitIsClear(registers, n)) {
4394 if (!success)
4395 return false;
4396
4397 offset = addr_byte_size * BitCount(registers);
4398 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4399 context.SetImmediateSigned(offset);
4400 addr_t addr = Rn + offset;
4401 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4402 addr))
4403 return false;
4404 }
4405
4406 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only
4407 // possible for encoding A1
4408 if (wback && BitIsSet(registers, n))
4409 return WriteBits32Unknown(n);
4410 }
4411 return true;
4412 }
4413
4414 // Load Register (immediate) calculates an address from a base register value
4415 // and an immediate offset, loads a word from memory, and writes to a register.
4416 // LDR (immediate, Thumb)
EmulateLDRRtRnImm(const uint32_t opcode,const ARMEncoding encoding)4417 bool EmulateInstructionARM::EmulateLDRRtRnImm(const uint32_t opcode,
4418 const ARMEncoding encoding) {
4419 #if 0
4420 // ARM pseudo code...
4421 if (ConditionPassed())
4422 {
4423 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
4424 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4425 address = if index then offset_addr else R[n];
4426 data = MemU[address,4];
4427 if wback then R[n] = offset_addr;
4428 if t == 15 then
4429 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
4430 elsif UnalignedSupport() || address<1:0> = '00' then
4431 R[t] = data;
4432 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
4433 }
4434 #endif
4435
4436 bool success = false;
4437
4438 if (ConditionPassed(opcode)) {
4439 uint32_t Rt; // the destination register
4440 uint32_t Rn; // the base register
4441 uint32_t imm32; // the immediate offset used to form the address
4442 addr_t offset_addr; // the offset address
4443 addr_t address; // the calculated address
4444 uint32_t data; // the literal data value from memory load
4445 bool add, index, wback;
4446 switch (encoding) {
4447 case eEncodingT1:
4448 Rt = Bits32(opcode, 2, 0);
4449 Rn = Bits32(opcode, 5, 3);
4450 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
4451 // index = TRUE; add = TRUE; wback = FALSE
4452 add = true;
4453 index = true;
4454 wback = false;
4455
4456 break;
4457
4458 case eEncodingT2:
4459 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
4460 Rt = Bits32(opcode, 10, 8);
4461 Rn = 13;
4462 imm32 = Bits32(opcode, 7, 0) << 2;
4463
4464 // index = TRUE; add = TRUE; wback = FALSE;
4465 index = true;
4466 add = true;
4467 wback = false;
4468
4469 break;
4470
4471 case eEncodingT3:
4472 // if Rn == '1111' then SEE LDR (literal);
4473 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4474 Rt = Bits32(opcode, 15, 12);
4475 Rn = Bits32(opcode, 19, 16);
4476 imm32 = Bits32(opcode, 11, 0);
4477
4478 // index = TRUE; add = TRUE; wback = FALSE;
4479 index = true;
4480 add = true;
4481 wback = false;
4482
4483 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
4484 if ((Rt == 15) && InITBlock() && !LastInITBlock())
4485 return false;
4486
4487 break;
4488
4489 case eEncodingT4:
4490 // if Rn == '1111' then SEE LDR (literal);
4491 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
4492 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 ==
4493 // '00000100' then SEE POP;
4494 // if P == '0' && W == '0' then UNDEFINED;
4495 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
4496 return false;
4497
4498 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4499 Rt = Bits32(opcode, 15, 12);
4500 Rn = Bits32(opcode, 19, 16);
4501 imm32 = Bits32(opcode, 7, 0);
4502
4503 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
4504 index = BitIsSet(opcode, 10);
4505 add = BitIsSet(opcode, 9);
4506 wback = BitIsSet(opcode, 8);
4507
4508 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock())
4509 // then UNPREDICTABLE;
4510 if ((wback && (Rn == Rt)) ||
4511 ((Rt == 15) && InITBlock() && !LastInITBlock()))
4512 return false;
4513
4514 break;
4515
4516 default:
4517 return false;
4518 }
4519 uint32_t base = ReadCoreReg(Rn, &success);
4520 if (!success)
4521 return false;
4522 if (add)
4523 offset_addr = base + imm32;
4524 else
4525 offset_addr = base - imm32;
4526
4527 address = (index ? offset_addr : base);
4528
4529 RegisterInfo base_reg;
4530 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn, base_reg);
4531 if (wback) {
4532 EmulateInstruction::Context ctx;
4533 if (Rn == 13) {
4534 ctx.type = eContextAdjustStackPointer;
4535 ctx.SetImmediateSigned((int32_t)(offset_addr - base));
4536 } else if (Rn == GetFramePointerRegisterNumber()) {
4537 ctx.type = eContextSetFramePointer;
4538 ctx.SetRegisterPlusOffset(base_reg, (int32_t)(offset_addr - base));
4539 } else {
4540 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
4541 ctx.SetRegisterPlusOffset(base_reg, (int32_t)(offset_addr - base));
4542 }
4543
4544 if (!WriteRegisterUnsigned(ctx, eRegisterKindDWARF, dwarf_r0 + Rn,
4545 offset_addr))
4546 return false;
4547 }
4548
4549 // Prepare to write to the Rt register.
4550 EmulateInstruction::Context context;
4551 context.type = EmulateInstruction::eContextRegisterLoad;
4552 context.SetRegisterPlusOffset(base_reg, (int32_t)(offset_addr - base));
4553
4554 // Read memory from the address.
4555 data = MemURead(context, address, 4, 0, &success);
4556 if (!success)
4557 return false;
4558
4559 if (Rt == 15) {
4560 if (Bits32(address, 1, 0) == 0) {
4561 if (!LoadWritePC(context, data))
4562 return false;
4563 } else
4564 return false;
4565 } else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) {
4566 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rt,
4567 data))
4568 return false;
4569 } else
4570 WriteBits32Unknown(Rt);
4571 }
4572 return true;
4573 }
4574
4575 // STM (Store Multiple Increment After) stores multiple registers to consecutive
4576 // memory locations using an address
4577 // from a base register. The consecutive memory locations start at this
4578 // address, and the address just above the last of those locations can
4579 // optionally be written back to the base register.
EmulateSTM(const uint32_t opcode,const ARMEncoding encoding)4580 bool EmulateInstructionARM::EmulateSTM(const uint32_t opcode,
4581 const ARMEncoding encoding) {
4582 #if 0
4583 if ConditionPassed() then
4584 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4585 address = R[n];
4586
4587 for i = 0 to 14
4588 if registers<i> == '1' then
4589 if i == n && wback && i != LowestSetBit(registers) then
4590 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
4591 else
4592 MemA[address,4] = R[i];
4593 address = address + 4;
4594
4595 if registers<15> == '1' then // Only possible for encoding A1
4596 MemA[address,4] = PCStoreValue();
4597 if wback then R[n] = R[n] + 4*BitCount(registers);
4598 #endif
4599
4600 bool success = false;
4601
4602 if (ConditionPassed(opcode)) {
4603 uint32_t n;
4604 uint32_t registers = 0;
4605 bool wback;
4606 const uint32_t addr_byte_size = GetAddressByteSize();
4607
4608 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4609 switch (encoding) {
4610 case eEncodingT1:
4611 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
4612 n = Bits32(opcode, 10, 8);
4613 registers = Bits32(opcode, 7, 0);
4614 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
4615 wback = true;
4616
4617 // if BitCount(registers) < 1 then UNPREDICTABLE;
4618 if (BitCount(registers) < 1)
4619 return false;
4620
4621 break;
4622
4623 case eEncodingT2:
4624 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4625 n = Bits32(opcode, 19, 16);
4626 registers = Bits32(opcode, 15, 0);
4627 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4628 wback = BitIsSet(opcode, 21);
4629
4630 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4631 if ((n == 15) || (BitCount(registers) < 2))
4632 return false;
4633
4634 // if wback && registers<n> == '1' then UNPREDICTABLE;
4635 if (wback && BitIsSet(registers, n))
4636 return false;
4637
4638 break;
4639
4640 case eEncodingA1:
4641 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4642 n = Bits32(opcode, 19, 16);
4643 registers = Bits32(opcode, 15, 0);
4644 wback = BitIsSet(opcode, 21);
4645
4646 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4647 if ((n == 15) || (BitCount(registers) < 1))
4648 return false;
4649
4650 break;
4651
4652 default:
4653 return false;
4654 }
4655
4656 // address = R[n];
4657 int32_t offset = 0;
4658 const addr_t address =
4659 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4660 if (!success)
4661 return false;
4662
4663 EmulateInstruction::Context context;
4664 context.type = EmulateInstruction::eContextRegisterStore;
4665 RegisterInfo base_reg;
4666 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4667
4668 // for i = 0 to 14
4669 uint32_t lowest_set_bit = 14;
4670 for (uint32_t i = 0; i < 14; ++i) {
4671 // if registers<i> == '1' then
4672 if (BitIsSet(registers, i)) {
4673 if (i < lowest_set_bit)
4674 lowest_set_bit = i;
4675 // if i == n && wback && i != LowestSetBit(registers) then
4676 if ((i == n) && wback && (i != lowest_set_bit))
4677 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings
4678 // T1 and A1
4679 WriteBits32UnknownToMemory(address + offset);
4680 else {
4681 // MemA[address,4] = R[i];
4682 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
4683 0, &success);
4684 if (!success)
4685 return false;
4686
4687 RegisterInfo data_reg;
4688 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg);
4689 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, offset);
4690 if (!MemAWrite(context, address + offset, data, addr_byte_size))
4691 return false;
4692 }
4693
4694 // address = address + 4;
4695 offset += addr_byte_size;
4696 }
4697 }
4698
4699 // if registers<15> == '1' then // Only possible for encoding A1
4700 // MemA[address,4] = PCStoreValue();
4701 if (BitIsSet(registers, 15)) {
4702 RegisterInfo pc_reg;
4703 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg);
4704 context.SetRegisterPlusOffset(pc_reg, 8);
4705 const uint32_t pc = ReadCoreReg(PC_REG, &success);
4706 if (!success)
4707 return false;
4708
4709 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4710 return false;
4711 }
4712
4713 // if wback then R[n] = R[n] + 4*BitCount(registers);
4714 if (wback) {
4715 offset = addr_byte_size * BitCount(registers);
4716 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4717 context.SetImmediateSigned(offset);
4718 addr_t data = address + offset;
4719 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4720 data))
4721 return false;
4722 }
4723 }
4724 return true;
4725 }
4726
4727 // STMDA (Store Multiple Decrement After) stores multiple registers to
4728 // consecutive memory locations using an address from a base register. The
4729 // consecutive memory locations end at this address, and the address just below
4730 // the lowest of those locations can optionally be written back to the base
4731 // register.
EmulateSTMDA(const uint32_t opcode,const ARMEncoding encoding)4732 bool EmulateInstructionARM::EmulateSTMDA(const uint32_t opcode,
4733 const ARMEncoding encoding) {
4734 #if 0
4735 if ConditionPassed() then
4736 EncodingSpecificOperations();
4737 address = R[n] - 4*BitCount(registers) + 4;
4738
4739 for i = 0 to 14
4740 if registers<i> == '1' then
4741 if i == n && wback && i != LowestSetBit(registers) then
4742 MemA[address,4] = bits(32) UNKNOWN;
4743 else
4744 MemA[address,4] = R[i];
4745 address = address + 4;
4746
4747 if registers<15> == '1' then
4748 MemA[address,4] = PCStoreValue();
4749
4750 if wback then R[n] = R[n] - 4*BitCount(registers);
4751 #endif
4752
4753 bool success = false;
4754
4755 if (ConditionPassed(opcode)) {
4756 uint32_t n;
4757 uint32_t registers = 0;
4758 bool wback;
4759 const uint32_t addr_byte_size = GetAddressByteSize();
4760
4761 // EncodingSpecificOperations();
4762 switch (encoding) {
4763 case eEncodingA1:
4764 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4765 n = Bits32(opcode, 19, 16);
4766 registers = Bits32(opcode, 15, 0);
4767 wback = BitIsSet(opcode, 21);
4768
4769 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4770 if ((n == 15) || (BitCount(registers) < 1))
4771 return false;
4772 break;
4773 default:
4774 return false;
4775 }
4776
4777 // address = R[n] - 4*BitCount(registers) + 4;
4778 int32_t offset = 0;
4779 addr_t Rn = ReadCoreReg(n, &success);
4780 if (!success)
4781 return false;
4782
4783 addr_t address = Rn - (addr_byte_size * BitCount(registers)) + 4;
4784
4785 EmulateInstruction::Context context;
4786 context.type = EmulateInstruction::eContextRegisterStore;
4787 RegisterInfo base_reg;
4788 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4789
4790 // for i = 0 to 14
4791 uint32_t lowest_bit_set = 14;
4792 for (uint32_t i = 0; i < 14; ++i) {
4793 // if registers<i> == '1' then
4794 if (BitIsSet(registers, i)) {
4795 if (i < lowest_bit_set)
4796 lowest_bit_set = i;
4797 // if i == n && wback && i != LowestSetBit(registers) then
4798 if ((i == n) && wback && (i != lowest_bit_set))
4799 // MemA[address,4] = bits(32) UNKNOWN;
4800 WriteBits32UnknownToMemory(address + offset);
4801 else {
4802 // MemA[address,4] = R[i];
4803 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
4804 0, &success);
4805 if (!success)
4806 return false;
4807
4808 RegisterInfo data_reg;
4809 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg);
4810 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
4811 Rn - (address + offset));
4812 if (!MemAWrite(context, address + offset, data, addr_byte_size))
4813 return false;
4814 }
4815
4816 // address = address + 4;
4817 offset += addr_byte_size;
4818 }
4819 }
4820
4821 // if registers<15> == '1' then
4822 // MemA[address,4] = PCStoreValue();
4823 if (BitIsSet(registers, 15)) {
4824 RegisterInfo pc_reg;
4825 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg);
4826 context.SetRegisterPlusOffset(pc_reg, 8);
4827 const uint32_t pc = ReadCoreReg(PC_REG, &success);
4828 if (!success)
4829 return false;
4830
4831 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4832 return false;
4833 }
4834
4835 // if wback then R[n] = R[n] - 4*BitCount(registers);
4836 if (wback) {
4837 offset = (addr_byte_size * BitCount(registers)) * -1;
4838 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4839 context.SetImmediateSigned(offset);
4840 addr_t data = Rn + offset;
4841 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4842 data))
4843 return false;
4844 }
4845 }
4846 return true;
4847 }
4848
4849 // STMDB (Store Multiple Decrement Before) stores multiple registers to
4850 // consecutive memory locations using an address from a base register. The
4851 // consecutive memory locations end just below this address, and the address of
4852 // the first of those locations can optionally be written back to the base
4853 // register.
EmulateSTMDB(const uint32_t opcode,const ARMEncoding encoding)4854 bool EmulateInstructionARM::EmulateSTMDB(const uint32_t opcode,
4855 const ARMEncoding encoding) {
4856 #if 0
4857 if ConditionPassed() then
4858 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4859 address = R[n] - 4*BitCount(registers);
4860
4861 for i = 0 to 14
4862 if registers<i> == '1' then
4863 if i == n && wback && i != LowestSetBit(registers) then
4864 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4865 else
4866 MemA[address,4] = R[i];
4867 address = address + 4;
4868
4869 if registers<15> == '1' then // Only possible for encoding A1
4870 MemA[address,4] = PCStoreValue();
4871
4872 if wback then R[n] = R[n] - 4*BitCount(registers);
4873 #endif
4874
4875 bool success = false;
4876
4877 if (ConditionPassed(opcode)) {
4878 uint32_t n;
4879 uint32_t registers = 0;
4880 bool wback;
4881 const uint32_t addr_byte_size = GetAddressByteSize();
4882
4883 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4884 switch (encoding) {
4885 case eEncodingT1:
4886 // if W == '1' && Rn == '1101' then SEE PUSH;
4887 if ((BitIsSet(opcode, 21)) && (Bits32(opcode, 19, 16) == 13)) {
4888 // See PUSH
4889 }
4890 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4891 n = Bits32(opcode, 19, 16);
4892 registers = Bits32(opcode, 15, 0);
4893 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4894 wback = BitIsSet(opcode, 21);
4895 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4896 if ((n == 15) || BitCount(registers) < 2)
4897 return false;
4898 // if wback && registers<n> == '1' then UNPREDICTABLE;
4899 if (wback && BitIsSet(registers, n))
4900 return false;
4901 break;
4902
4903 case eEncodingA1:
4904 // if W == '1' && Rn == '1101' && BitCount(register_list) >= 2 then SEE
4905 // PUSH;
4906 if (BitIsSet(opcode, 21) && (Bits32(opcode, 19, 16) == 13) &&
4907 BitCount(Bits32(opcode, 15, 0)) >= 2) {
4908 // See Push
4909 }
4910 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4911 n = Bits32(opcode, 19, 16);
4912 registers = Bits32(opcode, 15, 0);
4913 wback = BitIsSet(opcode, 21);
4914 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4915 if ((n == 15) || BitCount(registers) < 1)
4916 return false;
4917 break;
4918
4919 default:
4920 return false;
4921 }
4922
4923 // address = R[n] - 4*BitCount(registers);
4924
4925 int32_t offset = 0;
4926 addr_t Rn =
4927 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4928 if (!success)
4929 return false;
4930
4931 addr_t address = Rn - (addr_byte_size * BitCount(registers));
4932
4933 EmulateInstruction::Context context;
4934 context.type = EmulateInstruction::eContextRegisterStore;
4935 RegisterInfo base_reg;
4936 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4937
4938 // for i = 0 to 14
4939 uint32_t lowest_set_bit = 14;
4940 for (uint32_t i = 0; i < 14; ++i) {
4941 // if registers<i> == '1' then
4942 if (BitIsSet(registers, i)) {
4943 if (i < lowest_set_bit)
4944 lowest_set_bit = i;
4945 // if i == n && wback && i != LowestSetBit(registers) then
4946 if ((i == n) && wback && (i != lowest_set_bit))
4947 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding
4948 // A1
4949 WriteBits32UnknownToMemory(address + offset);
4950 else {
4951 // MemA[address,4] = R[i];
4952 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
4953 0, &success);
4954 if (!success)
4955 return false;
4956
4957 RegisterInfo data_reg;
4958 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg);
4959 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
4960 Rn - (address + offset));
4961 if (!MemAWrite(context, address + offset, data, addr_byte_size))
4962 return false;
4963 }
4964
4965 // address = address + 4;
4966 offset += addr_byte_size;
4967 }
4968 }
4969
4970 // if registers<15> == '1' then // Only possible for encoding A1
4971 // MemA[address,4] = PCStoreValue();
4972 if (BitIsSet(registers, 15)) {
4973 RegisterInfo pc_reg;
4974 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg);
4975 context.SetRegisterPlusOffset(pc_reg, 8);
4976 const uint32_t pc = ReadCoreReg(PC_REG, &success);
4977 if (!success)
4978 return false;
4979
4980 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4981 return false;
4982 }
4983
4984 // if wback then R[n] = R[n] - 4*BitCount(registers);
4985 if (wback) {
4986 offset = (addr_byte_size * BitCount(registers)) * -1;
4987 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4988 context.SetImmediateSigned(offset);
4989 addr_t data = Rn + offset;
4990 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4991 data))
4992 return false;
4993 }
4994 }
4995 return true;
4996 }
4997
4998 // STMIB (Store Multiple Increment Before) stores multiple registers to
4999 // consecutive memory locations using an address from a base register. The
5000 // consecutive memory locations start just above this address, and the address
5001 // of the last of those locations can optionally be written back to the base
5002 // register.
EmulateSTMIB(const uint32_t opcode,const ARMEncoding encoding)5003 bool EmulateInstructionARM::EmulateSTMIB(const uint32_t opcode,
5004 const ARMEncoding encoding) {
5005 #if 0
5006 if ConditionPassed() then
5007 EncodingSpecificOperations();
5008 address = R[n] + 4;
5009
5010 for i = 0 to 14
5011 if registers<i> == '1' then
5012 if i == n && wback && i != LowestSetBit(registers) then
5013 MemA[address,4] = bits(32) UNKNOWN;
5014 else
5015 MemA[address,4] = R[i];
5016 address = address + 4;
5017
5018 if registers<15> == '1' then
5019 MemA[address,4] = PCStoreValue();
5020
5021 if wback then R[n] = R[n] + 4*BitCount(registers);
5022 #endif
5023
5024 bool success = false;
5025
5026 if (ConditionPassed(opcode)) {
5027 uint32_t n;
5028 uint32_t registers = 0;
5029 bool wback;
5030 const uint32_t addr_byte_size = GetAddressByteSize();
5031
5032 // EncodingSpecificOperations();
5033 switch (encoding) {
5034 case eEncodingA1:
5035 // n = UInt(Rn); registers = register_list; wback = (W == '1');
5036 n = Bits32(opcode, 19, 16);
5037 registers = Bits32(opcode, 15, 0);
5038 wback = BitIsSet(opcode, 21);
5039
5040 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
5041 if ((n == 15) && (BitCount(registers) < 1))
5042 return false;
5043 break;
5044 default:
5045 return false;
5046 }
5047 // address = R[n] + 4;
5048
5049 int32_t offset = 0;
5050 addr_t Rn = ReadCoreReg(n, &success);
5051 if (!success)
5052 return false;
5053
5054 addr_t address = Rn + addr_byte_size;
5055
5056 EmulateInstruction::Context context;
5057 context.type = EmulateInstruction::eContextRegisterStore;
5058 RegisterInfo base_reg;
5059 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5060
5061 uint32_t lowest_set_bit = 14;
5062 // for i = 0 to 14
5063 for (uint32_t i = 0; i < 14; ++i) {
5064 // if registers<i> == '1' then
5065 if (BitIsSet(registers, i)) {
5066 if (i < lowest_set_bit)
5067 lowest_set_bit = i;
5068 // if i == n && wback && i != LowestSetBit(registers) then
5069 if ((i == n) && wback && (i != lowest_set_bit))
5070 // MemA[address,4] = bits(32) UNKNOWN;
5071 WriteBits32UnknownToMemory(address + offset);
5072 // else
5073 else {
5074 // MemA[address,4] = R[i];
5075 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
5076 0, &success);
5077 if (!success)
5078 return false;
5079
5080 RegisterInfo data_reg;
5081 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg);
5082 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
5083 offset + addr_byte_size);
5084 if (!MemAWrite(context, address + offset, data, addr_byte_size))
5085 return false;
5086 }
5087
5088 // address = address + 4;
5089 offset += addr_byte_size;
5090 }
5091 }
5092
5093 // if registers<15> == '1' then
5094 // MemA[address,4] = PCStoreValue();
5095 if (BitIsSet(registers, 15)) {
5096 RegisterInfo pc_reg;
5097 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg);
5098 context.SetRegisterPlusOffset(pc_reg, 8);
5099 const uint32_t pc = ReadCoreReg(PC_REG, &success);
5100 if (!success)
5101 return false;
5102
5103 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
5104 return false;
5105 }
5106
5107 // if wback then R[n] = R[n] + 4*BitCount(registers);
5108 if (wback) {
5109 offset = addr_byte_size * BitCount(registers);
5110 context.type = EmulateInstruction::eContextAdjustBaseRegister;
5111 context.SetImmediateSigned(offset);
5112 addr_t data = Rn + offset;
5113 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5114 data))
5115 return false;
5116 }
5117 }
5118 return true;
5119 }
5120
5121 // STR (store immediate) calculates an address from a base register value and an
5122 // immediate offset, and stores a word
5123 // from a register to memory. It can use offset, post-indexed, or pre-indexed
5124 // addressing.
EmulateSTRThumb(const uint32_t opcode,const ARMEncoding encoding)5125 bool EmulateInstructionARM::EmulateSTRThumb(const uint32_t opcode,
5126 const ARMEncoding encoding) {
5127 #if 0
5128 if ConditionPassed() then
5129 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5130 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5131 address = if index then offset_addr else R[n];
5132 if UnalignedSupport() || address<1:0> == '00' then
5133 MemU[address,4] = R[t];
5134 else // Can only occur before ARMv7
5135 MemU[address,4] = bits(32) UNKNOWN;
5136 if wback then R[n] = offset_addr;
5137 #endif
5138
5139 bool success = false;
5140
5141 if (ConditionPassed(opcode)) {
5142 const uint32_t addr_byte_size = GetAddressByteSize();
5143
5144 uint32_t t;
5145 uint32_t n;
5146 uint32_t imm32;
5147 bool index;
5148 bool add;
5149 bool wback;
5150 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
5151 switch (encoding) {
5152 case eEncodingT1:
5153 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
5154 t = Bits32(opcode, 2, 0);
5155 n = Bits32(opcode, 5, 3);
5156 imm32 = Bits32(opcode, 10, 6) << 2;
5157
5158 // index = TRUE; add = TRUE; wback = FALSE;
5159 index = true;
5160 add = false;
5161 wback = false;
5162 break;
5163
5164 case eEncodingT2:
5165 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
5166 t = Bits32(opcode, 10, 8);
5167 n = 13;
5168 imm32 = Bits32(opcode, 7, 0) << 2;
5169
5170 // index = TRUE; add = TRUE; wback = FALSE;
5171 index = true;
5172 add = true;
5173 wback = false;
5174 break;
5175
5176 case eEncodingT3:
5177 // if Rn == '1111' then UNDEFINED;
5178 if (Bits32(opcode, 19, 16) == 15)
5179 return false;
5180
5181 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5182 t = Bits32(opcode, 15, 12);
5183 n = Bits32(opcode, 19, 16);
5184 imm32 = Bits32(opcode, 11, 0);
5185
5186 // index = TRUE; add = TRUE; wback = FALSE;
5187 index = true;
5188 add = true;
5189 wback = false;
5190
5191 // if t == 15 then UNPREDICTABLE;
5192 if (t == 15)
5193 return false;
5194 break;
5195
5196 case eEncodingT4:
5197 // if P == '1' && U == '1' && W == '0' then SEE STRT;
5198 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 ==
5199 // '00000100' then SEE PUSH;
5200 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
5201 if ((Bits32(opcode, 19, 16) == 15) ||
5202 (BitIsClear(opcode, 10) && BitIsClear(opcode, 8)))
5203 return false;
5204
5205 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5206 t = Bits32(opcode, 15, 12);
5207 n = Bits32(opcode, 19, 16);
5208 imm32 = Bits32(opcode, 7, 0);
5209
5210 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
5211 index = BitIsSet(opcode, 10);
5212 add = BitIsSet(opcode, 9);
5213 wback = BitIsSet(opcode, 8);
5214
5215 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
5216 if ((t == 15) || (wback && (n == t)))
5217 return false;
5218 break;
5219
5220 default:
5221 return false;
5222 }
5223
5224 addr_t offset_addr;
5225 addr_t address;
5226
5227 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5228 uint32_t base_address = ReadCoreReg(n, &success);
5229 if (!success)
5230 return false;
5231
5232 if (add)
5233 offset_addr = base_address + imm32;
5234 else
5235 offset_addr = base_address - imm32;
5236
5237 // address = if index then offset_addr else R[n];
5238 if (index)
5239 address = offset_addr;
5240 else
5241 address = base_address;
5242
5243 EmulateInstruction::Context context;
5244 if (n == 13)
5245 context.type = eContextPushRegisterOnStack;
5246 else
5247 context.type = eContextRegisterStore;
5248
5249 RegisterInfo base_reg;
5250 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5251
5252 // if UnalignedSupport() || address<1:0> == '00' then
5253 if (UnalignedSupport() ||
5254 (BitIsClear(address, 1) && BitIsClear(address, 0))) {
5255 // MemU[address,4] = R[t];
5256 uint32_t data =
5257 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
5258 if (!success)
5259 return false;
5260
5261 RegisterInfo data_reg;
5262 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
5263 int32_t offset = address - base_address;
5264 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, offset);
5265 if (!MemUWrite(context, address, data, addr_byte_size))
5266 return false;
5267 } else {
5268 // MemU[address,4] = bits(32) UNKNOWN;
5269 WriteBits32UnknownToMemory(address);
5270 }
5271
5272 // if wback then R[n] = offset_addr;
5273 if (wback) {
5274 if (n == 13)
5275 context.type = eContextAdjustStackPointer;
5276 else
5277 context.type = eContextAdjustBaseRegister;
5278 context.SetAddress(offset_addr);
5279
5280 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5281 offset_addr))
5282 return false;
5283 }
5284 }
5285 return true;
5286 }
5287
5288 // STR (Store Register) calculates an address from a base register value and an
5289 // offset register value, stores a
5290 // word from a register to memory. The offset register value can optionally
5291 // be shifted.
EmulateSTRRegister(const uint32_t opcode,const ARMEncoding encoding)5292 bool EmulateInstructionARM::EmulateSTRRegister(const uint32_t opcode,
5293 const ARMEncoding encoding) {
5294 #if 0
5295 if ConditionPassed() then
5296 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5297 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5298 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5299 address = if index then offset_addr else R[n];
5300 if t == 15 then // Only possible for encoding A1
5301 data = PCStoreValue();
5302 else
5303 data = R[t];
5304 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
5305 MemU[address,4] = data;
5306 else // Can only occur before ARMv7
5307 MemU[address,4] = bits(32) UNKNOWN;
5308 if wback then R[n] = offset_addr;
5309 #endif
5310
5311 bool success = false;
5312
5313 if (ConditionPassed(opcode)) {
5314 const uint32_t addr_byte_size = GetAddressByteSize();
5315
5316 uint32_t t;
5317 uint32_t n;
5318 uint32_t m;
5319 ARM_ShifterType shift_t;
5320 uint32_t shift_n;
5321 bool index;
5322 bool add;
5323 bool wback;
5324
5325 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
5326 switch (encoding) {
5327 case eEncodingT1:
5328 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
5329 // in ThumbEE";
5330 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5331 t = Bits32(opcode, 2, 0);
5332 n = Bits32(opcode, 5, 3);
5333 m = Bits32(opcode, 8, 6);
5334
5335 // index = TRUE; add = TRUE; wback = FALSE;
5336 index = true;
5337 add = true;
5338 wback = false;
5339
5340 // (shift_t, shift_n) = (SRType_LSL, 0);
5341 shift_t = SRType_LSL;
5342 shift_n = 0;
5343 break;
5344
5345 case eEncodingT2:
5346 // if Rn == '1111' then UNDEFINED;
5347 if (Bits32(opcode, 19, 16) == 15)
5348 return false;
5349
5350 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5351 t = Bits32(opcode, 15, 12);
5352 n = Bits32(opcode, 19, 16);
5353 m = Bits32(opcode, 3, 0);
5354
5355 // index = TRUE; add = TRUE; wback = FALSE;
5356 index = true;
5357 add = true;
5358 wback = false;
5359
5360 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5361 shift_t = SRType_LSL;
5362 shift_n = Bits32(opcode, 5, 4);
5363
5364 // if t == 15 || BadReg(m) then UNPREDICTABLE;
5365 if ((t == 15) || (BadReg(m)))
5366 return false;
5367 break;
5368
5369 case eEncodingA1: {
5370 // if P == '0' && W == '1' then SEE STRT;
5371 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5372 t = Bits32(opcode, 15, 12);
5373 n = Bits32(opcode, 19, 16);
5374 m = Bits32(opcode, 3, 0);
5375
5376 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
5377 // (W == '1');
5378 index = BitIsSet(opcode, 24);
5379 add = BitIsSet(opcode, 23);
5380 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
5381
5382 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5383 uint32_t typ = Bits32(opcode, 6, 5);
5384 uint32_t imm5 = Bits32(opcode, 11, 7);
5385 shift_n = DecodeImmShift(typ, imm5, shift_t);
5386
5387 // if m == 15 then UNPREDICTABLE;
5388 if (m == 15)
5389 return false;
5390
5391 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5392 if (wback && ((n == 15) || (n == t)))
5393 return false;
5394
5395 break;
5396 }
5397 default:
5398 return false;
5399 }
5400
5401 addr_t offset_addr;
5402 addr_t address;
5403 int32_t offset = 0;
5404
5405 addr_t base_address =
5406 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5407 if (!success)
5408 return false;
5409
5410 uint32_t Rm_data =
5411 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5412 if (!success)
5413 return false;
5414
5415 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5416 offset = Shift(Rm_data, shift_t, shift_n, APSR_C, &success);
5417 if (!success)
5418 return false;
5419
5420 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5421 if (add)
5422 offset_addr = base_address + offset;
5423 else
5424 offset_addr = base_address - offset;
5425
5426 // address = if index then offset_addr else R[n];
5427 if (index)
5428 address = offset_addr;
5429 else
5430 address = base_address;
5431
5432 uint32_t data;
5433 // if t == 15 then // Only possible for encoding A1
5434 if (t == 15)
5435 // data = PCStoreValue();
5436 data = ReadCoreReg(PC_REG, &success);
5437 else
5438 // data = R[t];
5439 data =
5440 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
5441
5442 if (!success)
5443 return false;
5444
5445 EmulateInstruction::Context context;
5446 context.type = eContextRegisterStore;
5447
5448 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() ==
5449 // InstrSet_ARM then
5450 if (UnalignedSupport() ||
5451 (BitIsClear(address, 1) && BitIsClear(address, 0)) ||
5452 CurrentInstrSet() == eModeARM) {
5453 // MemU[address,4] = data;
5454
5455 RegisterInfo base_reg;
5456 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5457
5458 RegisterInfo data_reg;
5459 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
5460
5461 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
5462 address - base_address);
5463 if (!MemUWrite(context, address, data, addr_byte_size))
5464 return false;
5465
5466 } else
5467 // MemU[address,4] = bits(32) UNKNOWN;
5468 WriteBits32UnknownToMemory(address);
5469
5470 // if wback then R[n] = offset_addr;
5471 if (wback) {
5472 context.type = eContextRegisterLoad;
5473 context.SetAddress(offset_addr);
5474 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5475 offset_addr))
5476 return false;
5477 }
5478 }
5479 return true;
5480 }
5481
EmulateSTRBThumb(const uint32_t opcode,const ARMEncoding encoding)5482 bool EmulateInstructionARM::EmulateSTRBThumb(const uint32_t opcode,
5483 const ARMEncoding encoding) {
5484 #if 0
5485 if ConditionPassed() then
5486 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5487 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5488 address = if index then offset_addr else R[n];
5489 MemU[address,1] = R[t]<7:0>;
5490 if wback then R[n] = offset_addr;
5491 #endif
5492
5493 bool success = false;
5494
5495 if (ConditionPassed(opcode)) {
5496 uint32_t t;
5497 uint32_t n;
5498 uint32_t imm32;
5499 bool index;
5500 bool add;
5501 bool wback;
5502 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5503 switch (encoding) {
5504 case eEncodingT1:
5505 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5506 t = Bits32(opcode, 2, 0);
5507 n = Bits32(opcode, 5, 3);
5508 imm32 = Bits32(opcode, 10, 6);
5509
5510 // index = TRUE; add = TRUE; wback = FALSE;
5511 index = true;
5512 add = true;
5513 wback = false;
5514 break;
5515
5516 case eEncodingT2:
5517 // if Rn == '1111' then UNDEFINED;
5518 if (Bits32(opcode, 19, 16) == 15)
5519 return false;
5520
5521 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5522 t = Bits32(opcode, 15, 12);
5523 n = Bits32(opcode, 19, 16);
5524 imm32 = Bits32(opcode, 11, 0);
5525
5526 // index = TRUE; add = TRUE; wback = FALSE;
5527 index = true;
5528 add = true;
5529 wback = false;
5530
5531 // if BadReg(t) then UNPREDICTABLE;
5532 if (BadReg(t))
5533 return false;
5534 break;
5535
5536 case eEncodingT3:
5537 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
5538 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
5539 if (Bits32(opcode, 19, 16) == 15)
5540 return false;
5541
5542 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5543 t = Bits32(opcode, 15, 12);
5544 n = Bits32(opcode, 19, 16);
5545 imm32 = Bits32(opcode, 7, 0);
5546
5547 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
5548 index = BitIsSet(opcode, 10);
5549 add = BitIsSet(opcode, 9);
5550 wback = BitIsSet(opcode, 8);
5551
5552 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
5553 if ((BadReg(t)) || (wback && (n == t)))
5554 return false;
5555 break;
5556
5557 default:
5558 return false;
5559 }
5560
5561 addr_t offset_addr;
5562 addr_t address;
5563 addr_t base_address =
5564 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5565 if (!success)
5566 return false;
5567
5568 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5569 if (add)
5570 offset_addr = base_address + imm32;
5571 else
5572 offset_addr = base_address - imm32;
5573
5574 // address = if index then offset_addr else R[n];
5575 if (index)
5576 address = offset_addr;
5577 else
5578 address = base_address;
5579
5580 // MemU[address,1] = R[t]<7:0>
5581 RegisterInfo base_reg;
5582 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5583
5584 RegisterInfo data_reg;
5585 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
5586
5587 EmulateInstruction::Context context;
5588 context.type = eContextRegisterStore;
5589 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
5590 address - base_address);
5591
5592 uint32_t data =
5593 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
5594 if (!success)
5595 return false;
5596
5597 data = Bits32(data, 7, 0);
5598
5599 if (!MemUWrite(context, address, data, 1))
5600 return false;
5601
5602 // if wback then R[n] = offset_addr;
5603 if (wback) {
5604 context.type = eContextRegisterLoad;
5605 context.SetAddress(offset_addr);
5606 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5607 offset_addr))
5608 return false;
5609 }
5610 }
5611
5612 return true;
5613 }
5614
5615 // STRH (register) calculates an address from a base register value and an
5616 // offset register value, and stores a
5617 // halfword from a register to memory. The offset register value can be
5618 // shifted left by 0, 1, 2, or 3 bits.
EmulateSTRHRegister(const uint32_t opcode,const ARMEncoding encoding)5619 bool EmulateInstructionARM::EmulateSTRHRegister(const uint32_t opcode,
5620 const ARMEncoding encoding) {
5621 #if 0
5622 if ConditionPassed() then
5623 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5624 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5625 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5626 address = if index then offset_addr else R[n];
5627 if UnalignedSupport() || address<0> == '0' then
5628 MemU[address,2] = R[t]<15:0>;
5629 else // Can only occur before ARMv7
5630 MemU[address,2] = bits(16) UNKNOWN;
5631 if wback then R[n] = offset_addr;
5632 #endif
5633
5634 bool success = false;
5635
5636 if (ConditionPassed(opcode)) {
5637 uint32_t t;
5638 uint32_t n;
5639 uint32_t m;
5640 bool index;
5641 bool add;
5642 bool wback;
5643 ARM_ShifterType shift_t;
5644 uint32_t shift_n;
5645
5646 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5647 switch (encoding) {
5648 case eEncodingT1:
5649 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
5650 // in ThumbEE";
5651 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5652 t = Bits32(opcode, 2, 0);
5653 n = Bits32(opcode, 5, 3);
5654 m = Bits32(opcode, 8, 6);
5655
5656 // index = TRUE; add = TRUE; wback = FALSE;
5657 index = true;
5658 add = true;
5659 wback = false;
5660
5661 // (shift_t, shift_n) = (SRType_LSL, 0);
5662 shift_t = SRType_LSL;
5663 shift_n = 0;
5664
5665 break;
5666
5667 case eEncodingT2:
5668 // if Rn == '1111' then UNDEFINED;
5669 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5670 t = Bits32(opcode, 15, 12);
5671 n = Bits32(opcode, 19, 16);
5672 m = Bits32(opcode, 3, 0);
5673 if (n == 15)
5674 return false;
5675
5676 // index = TRUE; add = TRUE; wback = FALSE;
5677 index = true;
5678 add = true;
5679 wback = false;
5680
5681 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5682 shift_t = SRType_LSL;
5683 shift_n = Bits32(opcode, 5, 4);
5684
5685 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
5686 if (BadReg(t) || BadReg(m))
5687 return false;
5688
5689 break;
5690
5691 case eEncodingA1:
5692 // if P == '0' && W == '1' then SEE STRHT;
5693 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5694 t = Bits32(opcode, 15, 12);
5695 n = Bits32(opcode, 19, 16);
5696 m = Bits32(opcode, 3, 0);
5697
5698 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
5699 // (W == '1');
5700 index = BitIsSet(opcode, 24);
5701 add = BitIsSet(opcode, 23);
5702 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
5703
5704 // (shift_t, shift_n) = (SRType_LSL, 0);
5705 shift_t = SRType_LSL;
5706 shift_n = 0;
5707
5708 // if t == 15 || m == 15 then UNPREDICTABLE;
5709 if ((t == 15) || (m == 15))
5710 return false;
5711
5712 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5713 if (wback && ((n == 15) || (n == t)))
5714 return false;
5715
5716 break;
5717
5718 default:
5719 return false;
5720 }
5721
5722 uint32_t Rm = ReadCoreReg(m, &success);
5723 if (!success)
5724 return false;
5725
5726 uint32_t Rn = ReadCoreReg(n, &success);
5727 if (!success)
5728 return false;
5729
5730 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5731 uint32_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
5732 if (!success)
5733 return false;
5734
5735 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5736 addr_t offset_addr;
5737 if (add)
5738 offset_addr = Rn + offset;
5739 else
5740 offset_addr = Rn - offset;
5741
5742 // address = if index then offset_addr else R[n];
5743 addr_t address;
5744 if (index)
5745 address = offset_addr;
5746 else
5747 address = Rn;
5748
5749 EmulateInstruction::Context context;
5750 context.type = eContextRegisterStore;
5751 RegisterInfo base_reg;
5752 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5753 RegisterInfo offset_reg;
5754 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
5755
5756 // if UnalignedSupport() || address<0> == '0' then
5757 if (UnalignedSupport() || BitIsClear(address, 0)) {
5758 // MemU[address,2] = R[t]<15:0>;
5759 uint32_t Rt = ReadCoreReg(t, &success);
5760 if (!success)
5761 return false;
5762
5763 EmulateInstruction::Context context;
5764 context.type = eContextRegisterStore;
5765 RegisterInfo base_reg;
5766 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5767 RegisterInfo offset_reg;
5768 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
5769 RegisterInfo data_reg;
5770 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
5771 context.SetRegisterToRegisterPlusIndirectOffset(base_reg, offset_reg,
5772 data_reg);
5773
5774 if (!MemUWrite(context, address, Bits32(Rt, 15, 0), 2))
5775 return false;
5776 } else // Can only occur before ARMv7
5777 {
5778 // MemU[address,2] = bits(16) UNKNOWN;
5779 }
5780
5781 // if wback then R[n] = offset_addr;
5782 if (wback) {
5783 context.type = eContextAdjustBaseRegister;
5784 context.SetAddress(offset_addr);
5785 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5786 offset_addr))
5787 return false;
5788 }
5789 }
5790
5791 return true;
5792 }
5793
5794 // Add with Carry (immediate) adds an immediate value and the carry flag value
5795 // to a register value, and writes the result to the destination register. It
5796 // can optionally update the condition flags based on the result.
EmulateADCImm(const uint32_t opcode,const ARMEncoding encoding)5797 bool EmulateInstructionARM::EmulateADCImm(const uint32_t opcode,
5798 const ARMEncoding encoding) {
5799 #if 0
5800 // ARM pseudo code...
5801 if ConditionPassed() then
5802 EncodingSpecificOperations();
5803 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5804 if d == 15 then // Can only occur for ARM encoding
5805 ALUWritePC(result); // setflags is always FALSE here
5806 else
5807 R[d] = result;
5808 if setflags then
5809 APSR.N = result<31>;
5810 APSR.Z = IsZeroBit(result);
5811 APSR.C = carry;
5812 APSR.V = overflow;
5813 #endif
5814
5815 bool success = false;
5816
5817 if (ConditionPassed(opcode)) {
5818 uint32_t Rd, Rn;
5819 uint32_t
5820 imm32; // the immediate value to be added to the value obtained from Rn
5821 bool setflags;
5822 switch (encoding) {
5823 case eEncodingT1:
5824 Rd = Bits32(opcode, 11, 8);
5825 Rn = Bits32(opcode, 19, 16);
5826 setflags = BitIsSet(opcode, 20);
5827 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5828 if (BadReg(Rd) || BadReg(Rn))
5829 return false;
5830 break;
5831 case eEncodingA1:
5832 Rd = Bits32(opcode, 15, 12);
5833 Rn = Bits32(opcode, 19, 16);
5834 setflags = BitIsSet(opcode, 20);
5835 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5836
5837 if (Rd == 15 && setflags)
5838 return EmulateSUBSPcLrEtc(opcode, encoding);
5839 break;
5840 default:
5841 return false;
5842 }
5843
5844 // Read the first operand.
5845 int32_t val1 = ReadCoreReg(Rn, &success);
5846 if (!success)
5847 return false;
5848
5849 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5850
5851 EmulateInstruction::Context context;
5852 context.type = EmulateInstruction::eContextImmediate;
5853 context.SetNoArgs();
5854
5855 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
5856 res.carry_out, res.overflow))
5857 return false;
5858 }
5859 return true;
5860 }
5861
5862 // Add with Carry (register) adds a register value, the carry flag value, and
5863 // an optionally-shifted register value, and writes the result to the
5864 // destination register. It can optionally update the condition flags based on
5865 // the result.
EmulateADCReg(const uint32_t opcode,const ARMEncoding encoding)5866 bool EmulateInstructionARM::EmulateADCReg(const uint32_t opcode,
5867 const ARMEncoding encoding) {
5868 #if 0
5869 // ARM pseudo code...
5870 if ConditionPassed() then
5871 EncodingSpecificOperations();
5872 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5873 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5874 if d == 15 then // Can only occur for ARM encoding
5875 ALUWritePC(result); // setflags is always FALSE here
5876 else
5877 R[d] = result;
5878 if setflags then
5879 APSR.N = result<31>;
5880 APSR.Z = IsZeroBit(result);
5881 APSR.C = carry;
5882 APSR.V = overflow;
5883 #endif
5884
5885 bool success = false;
5886
5887 if (ConditionPassed(opcode)) {
5888 uint32_t Rd, Rn, Rm;
5889 ARM_ShifterType shift_t;
5890 uint32_t shift_n; // the shift applied to the value read from Rm
5891 bool setflags;
5892 switch (encoding) {
5893 case eEncodingT1:
5894 Rd = Rn = Bits32(opcode, 2, 0);
5895 Rm = Bits32(opcode, 5, 3);
5896 setflags = !InITBlock();
5897 shift_t = SRType_LSL;
5898 shift_n = 0;
5899 break;
5900 case eEncodingT2:
5901 Rd = Bits32(opcode, 11, 8);
5902 Rn = Bits32(opcode, 19, 16);
5903 Rm = Bits32(opcode, 3, 0);
5904 setflags = BitIsSet(opcode, 20);
5905 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5906 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5907 return false;
5908 break;
5909 case eEncodingA1:
5910 Rd = Bits32(opcode, 15, 12);
5911 Rn = Bits32(opcode, 19, 16);
5912 Rm = Bits32(opcode, 3, 0);
5913 setflags = BitIsSet(opcode, 20);
5914 shift_n = DecodeImmShiftARM(opcode, shift_t);
5915
5916 if (Rd == 15 && setflags)
5917 return EmulateSUBSPcLrEtc(opcode, encoding);
5918 break;
5919 default:
5920 return false;
5921 }
5922
5923 // Read the first operand.
5924 int32_t val1 = ReadCoreReg(Rn, &success);
5925 if (!success)
5926 return false;
5927
5928 // Read the second operand.
5929 int32_t val2 = ReadCoreReg(Rm, &success);
5930 if (!success)
5931 return false;
5932
5933 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
5934 if (!success)
5935 return false;
5936 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5937
5938 EmulateInstruction::Context context;
5939 context.type = EmulateInstruction::eContextImmediate;
5940 context.SetNoArgs();
5941
5942 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
5943 res.carry_out, res.overflow))
5944 return false;
5945 }
5946 return true;
5947 }
5948
5949 // This instruction adds an immediate value to the PC value to form a PC-
5950 // relative address, and writes the result to the destination register.
EmulateADR(const uint32_t opcode,const ARMEncoding encoding)5951 bool EmulateInstructionARM::EmulateADR(const uint32_t opcode,
5952 const ARMEncoding encoding) {
5953 #if 0
5954 // ARM pseudo code...
5955 if ConditionPassed() then
5956 EncodingSpecificOperations();
5957 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5958 if d == 15 then // Can only occur for ARM encodings
5959 ALUWritePC(result);
5960 else
5961 R[d] = result;
5962 #endif
5963
5964 bool success = false;
5965
5966 if (ConditionPassed(opcode)) {
5967 uint32_t Rd;
5968 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5969 bool add;
5970 switch (encoding) {
5971 case eEncodingT1:
5972 Rd = Bits32(opcode, 10, 8);
5973 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5974 add = true;
5975 break;
5976 case eEncodingT2:
5977 case eEncodingT3:
5978 Rd = Bits32(opcode, 11, 8);
5979 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5980 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5981 if (BadReg(Rd))
5982 return false;
5983 break;
5984 case eEncodingA1:
5985 case eEncodingA2:
5986 Rd = Bits32(opcode, 15, 12);
5987 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5988 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5989 break;
5990 default:
5991 return false;
5992 }
5993
5994 // Read the PC value.
5995 uint32_t pc = ReadCoreReg(PC_REG, &success);
5996 if (!success)
5997 return false;
5998
5999 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
6000
6001 EmulateInstruction::Context context;
6002 context.type = EmulateInstruction::eContextImmediate;
6003 context.SetNoArgs();
6004
6005 if (!WriteCoreReg(context, result, Rd))
6006 return false;
6007 }
6008 return true;
6009 }
6010
6011 // This instruction performs a bitwise AND of a register value and an immediate
6012 // value, and writes the result to the destination register. It can optionally
6013 // update the condition flags based on the result.
EmulateANDImm(const uint32_t opcode,const ARMEncoding encoding)6014 bool EmulateInstructionARM::EmulateANDImm(const uint32_t opcode,
6015 const ARMEncoding encoding) {
6016 #if 0
6017 // ARM pseudo code...
6018 if ConditionPassed() then
6019 EncodingSpecificOperations();
6020 result = R[n] AND imm32;
6021 if d == 15 then // Can only occur for ARM encoding
6022 ALUWritePC(result); // setflags is always FALSE here
6023 else
6024 R[d] = result;
6025 if setflags then
6026 APSR.N = result<31>;
6027 APSR.Z = IsZeroBit(result);
6028 APSR.C = carry;
6029 // APSR.V unchanged
6030 #endif
6031
6032 bool success = false;
6033
6034 if (ConditionPassed(opcode)) {
6035 uint32_t Rd, Rn;
6036 uint32_t
6037 imm32; // the immediate value to be ANDed to the value obtained from Rn
6038 bool setflags;
6039 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6040 switch (encoding) {
6041 case eEncodingT1:
6042 Rd = Bits32(opcode, 11, 8);
6043 Rn = Bits32(opcode, 19, 16);
6044 setflags = BitIsSet(opcode, 20);
6045 imm32 = ThumbExpandImm_C(
6046 opcode, APSR_C,
6047 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6048 // if Rd == '1111' && S == '1' then SEE TST (immediate);
6049 if (Rd == 15 && setflags)
6050 return EmulateTSTImm(opcode, eEncodingT1);
6051 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
6052 return false;
6053 break;
6054 case eEncodingA1:
6055 Rd = Bits32(opcode, 15, 12);
6056 Rn = Bits32(opcode, 19, 16);
6057 setflags = BitIsSet(opcode, 20);
6058 imm32 =
6059 ARMExpandImm_C(opcode, APSR_C,
6060 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6061
6062 if (Rd == 15 && setflags)
6063 return EmulateSUBSPcLrEtc(opcode, encoding);
6064 break;
6065 default:
6066 return false;
6067 }
6068
6069 // Read the first operand.
6070 uint32_t val1 = ReadCoreReg(Rn, &success);
6071 if (!success)
6072 return false;
6073
6074 uint32_t result = val1 & imm32;
6075
6076 EmulateInstruction::Context context;
6077 context.type = EmulateInstruction::eContextImmediate;
6078 context.SetNoArgs();
6079
6080 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6081 return false;
6082 }
6083 return true;
6084 }
6085
6086 // This instruction performs a bitwise AND of a register value and an
6087 // optionally-shifted register value, and writes the result to the destination
6088 // register. It can optionally update the condition flags based on the result.
EmulateANDReg(const uint32_t opcode,const ARMEncoding encoding)6089 bool EmulateInstructionARM::EmulateANDReg(const uint32_t opcode,
6090 const ARMEncoding encoding) {
6091 #if 0
6092 // ARM pseudo code...
6093 if ConditionPassed() then
6094 EncodingSpecificOperations();
6095 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6096 result = R[n] AND shifted;
6097 if d == 15 then // Can only occur for ARM encoding
6098 ALUWritePC(result); // setflags is always FALSE here
6099 else
6100 R[d] = result;
6101 if setflags then
6102 APSR.N = result<31>;
6103 APSR.Z = IsZeroBit(result);
6104 APSR.C = carry;
6105 // APSR.V unchanged
6106 #endif
6107
6108 bool success = false;
6109
6110 if (ConditionPassed(opcode)) {
6111 uint32_t Rd, Rn, Rm;
6112 ARM_ShifterType shift_t;
6113 uint32_t shift_n; // the shift applied to the value read from Rm
6114 bool setflags;
6115 uint32_t carry;
6116 switch (encoding) {
6117 case eEncodingT1:
6118 Rd = Rn = Bits32(opcode, 2, 0);
6119 Rm = Bits32(opcode, 5, 3);
6120 setflags = !InITBlock();
6121 shift_t = SRType_LSL;
6122 shift_n = 0;
6123 break;
6124 case eEncodingT2:
6125 Rd = Bits32(opcode, 11, 8);
6126 Rn = Bits32(opcode, 19, 16);
6127 Rm = Bits32(opcode, 3, 0);
6128 setflags = BitIsSet(opcode, 20);
6129 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6130 // if Rd == '1111' && S == '1' then SEE TST (register);
6131 if (Rd == 15 && setflags)
6132 return EmulateTSTReg(opcode, eEncodingT2);
6133 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
6134 return false;
6135 break;
6136 case eEncodingA1:
6137 Rd = Bits32(opcode, 15, 12);
6138 Rn = Bits32(opcode, 19, 16);
6139 Rm = Bits32(opcode, 3, 0);
6140 setflags = BitIsSet(opcode, 20);
6141 shift_n = DecodeImmShiftARM(opcode, shift_t);
6142
6143 if (Rd == 15 && setflags)
6144 return EmulateSUBSPcLrEtc(opcode, encoding);
6145 break;
6146 default:
6147 return false;
6148 }
6149
6150 // Read the first operand.
6151 uint32_t val1 = ReadCoreReg(Rn, &success);
6152 if (!success)
6153 return false;
6154
6155 // Read the second operand.
6156 uint32_t val2 = ReadCoreReg(Rm, &success);
6157 if (!success)
6158 return false;
6159
6160 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
6161 if (!success)
6162 return false;
6163 uint32_t result = val1 & shifted;
6164
6165 EmulateInstruction::Context context;
6166 context.type = EmulateInstruction::eContextImmediate;
6167 context.SetNoArgs();
6168
6169 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6170 return false;
6171 }
6172 return true;
6173 }
6174
6175 // Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and
6176 // the complement of an immediate value, and writes the result to the
6177 // destination register. It can optionally update the condition flags based on
6178 // the result.
EmulateBICImm(const uint32_t opcode,const ARMEncoding encoding)6179 bool EmulateInstructionARM::EmulateBICImm(const uint32_t opcode,
6180 const ARMEncoding encoding) {
6181 #if 0
6182 // ARM pseudo code...
6183 if ConditionPassed() then
6184 EncodingSpecificOperations();
6185 result = R[n] AND NOT(imm32);
6186 if d == 15 then // Can only occur for ARM encoding
6187 ALUWritePC(result); // setflags is always FALSE here
6188 else
6189 R[d] = result;
6190 if setflags then
6191 APSR.N = result<31>;
6192 APSR.Z = IsZeroBit(result);
6193 APSR.C = carry;
6194 // APSR.V unchanged
6195 #endif
6196
6197 bool success = false;
6198
6199 if (ConditionPassed(opcode)) {
6200 uint32_t Rd, Rn;
6201 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to
6202 // the value obtained from Rn
6203 bool setflags;
6204 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6205 switch (encoding) {
6206 case eEncodingT1:
6207 Rd = Bits32(opcode, 11, 8);
6208 Rn = Bits32(opcode, 19, 16);
6209 setflags = BitIsSet(opcode, 20);
6210 imm32 = ThumbExpandImm_C(
6211 opcode, APSR_C,
6212 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6213 if (BadReg(Rd) || BadReg(Rn))
6214 return false;
6215 break;
6216 case eEncodingA1:
6217 Rd = Bits32(opcode, 15, 12);
6218 Rn = Bits32(opcode, 19, 16);
6219 setflags = BitIsSet(opcode, 20);
6220 imm32 =
6221 ARMExpandImm_C(opcode, APSR_C,
6222 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6223
6224 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
6225 // instructions;
6226 if (Rd == 15 && setflags)
6227 return EmulateSUBSPcLrEtc(opcode, encoding);
6228 break;
6229 default:
6230 return false;
6231 }
6232
6233 // Read the first operand.
6234 uint32_t val1 = ReadCoreReg(Rn, &success);
6235 if (!success)
6236 return false;
6237
6238 uint32_t result = val1 & ~imm32;
6239
6240 EmulateInstruction::Context context;
6241 context.type = EmulateInstruction::eContextImmediate;
6242 context.SetNoArgs();
6243
6244 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6245 return false;
6246 }
6247 return true;
6248 }
6249
6250 // Bitwise Bit Clear (register) performs a bitwise AND of a register value and
6251 // the complement of an optionally-shifted register value, and writes the
6252 // result to the destination register. It can optionally update the condition
6253 // flags based on the result.
EmulateBICReg(const uint32_t opcode,const ARMEncoding encoding)6254 bool EmulateInstructionARM::EmulateBICReg(const uint32_t opcode,
6255 const ARMEncoding encoding) {
6256 #if 0
6257 // ARM pseudo code...
6258 if ConditionPassed() then
6259 EncodingSpecificOperations();
6260 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6261 result = R[n] AND NOT(shifted);
6262 if d == 15 then // Can only occur for ARM encoding
6263 ALUWritePC(result); // setflags is always FALSE here
6264 else
6265 R[d] = result;
6266 if setflags then
6267 APSR.N = result<31>;
6268 APSR.Z = IsZeroBit(result);
6269 APSR.C = carry;
6270 // APSR.V unchanged
6271 #endif
6272
6273 bool success = false;
6274
6275 if (ConditionPassed(opcode)) {
6276 uint32_t Rd, Rn, Rm;
6277 ARM_ShifterType shift_t;
6278 uint32_t shift_n; // the shift applied to the value read from Rm
6279 bool setflags;
6280 uint32_t carry;
6281 switch (encoding) {
6282 case eEncodingT1:
6283 Rd = Rn = Bits32(opcode, 2, 0);
6284 Rm = Bits32(opcode, 5, 3);
6285 setflags = !InITBlock();
6286 shift_t = SRType_LSL;
6287 shift_n = 0;
6288 break;
6289 case eEncodingT2:
6290 Rd = Bits32(opcode, 11, 8);
6291 Rn = Bits32(opcode, 19, 16);
6292 Rm = Bits32(opcode, 3, 0);
6293 setflags = BitIsSet(opcode, 20);
6294 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6295 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
6296 return false;
6297 break;
6298 case eEncodingA1:
6299 Rd = Bits32(opcode, 15, 12);
6300 Rn = Bits32(opcode, 19, 16);
6301 Rm = Bits32(opcode, 3, 0);
6302 setflags = BitIsSet(opcode, 20);
6303 shift_n = DecodeImmShiftARM(opcode, shift_t);
6304
6305 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
6306 // instructions;
6307 if (Rd == 15 && setflags)
6308 return EmulateSUBSPcLrEtc(opcode, encoding);
6309 break;
6310 default:
6311 return false;
6312 }
6313
6314 // Read the first operand.
6315 uint32_t val1 = ReadCoreReg(Rn, &success);
6316 if (!success)
6317 return false;
6318
6319 // Read the second operand.
6320 uint32_t val2 = ReadCoreReg(Rm, &success);
6321 if (!success)
6322 return false;
6323
6324 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
6325 if (!success)
6326 return false;
6327 uint32_t result = val1 & ~shifted;
6328
6329 EmulateInstruction::Context context;
6330 context.type = EmulateInstruction::eContextImmediate;
6331 context.SetNoArgs();
6332
6333 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6334 return false;
6335 }
6336 return true;
6337 }
6338
6339 // LDR (immediate, ARM) calculates an address from a base register value and an
6340 // immediate offset, loads a word
6341 // from memory, and writes it to a register. It can use offset, post-indexed,
6342 // or pre-indexed addressing.
EmulateLDRImmediateARM(const uint32_t opcode,const ARMEncoding encoding)6343 bool EmulateInstructionARM::EmulateLDRImmediateARM(const uint32_t opcode,
6344 const ARMEncoding encoding) {
6345 #if 0
6346 if ConditionPassed() then
6347 EncodingSpecificOperations();
6348 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6349 address = if index then offset_addr else R[n];
6350 data = MemU[address,4];
6351 if wback then R[n] = offset_addr;
6352 if t == 15 then
6353 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6354 elsif UnalignedSupport() || address<1:0> = '00' then
6355 R[t] = data;
6356 else // Can only apply before ARMv7
6357 R[t] = ROR(data, 8*UInt(address<1:0>));
6358 #endif
6359
6360 bool success = false;
6361
6362 if (ConditionPassed(opcode)) {
6363 const uint32_t addr_byte_size = GetAddressByteSize();
6364
6365 uint32_t t;
6366 uint32_t n;
6367 uint32_t imm32;
6368 bool index;
6369 bool add;
6370 bool wback;
6371
6372 switch (encoding) {
6373 case eEncodingA1:
6374 // if Rn == '1111' then SEE LDR (literal);
6375 // if P == '0' && W == '1' then SEE LDRT;
6376 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 ==
6377 // '000000000100' then SEE POP;
6378 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6379 t = Bits32(opcode, 15, 12);
6380 n = Bits32(opcode, 19, 16);
6381 imm32 = Bits32(opcode, 11, 0);
6382
6383 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6384 // (W == '1');
6385 index = BitIsSet(opcode, 24);
6386 add = BitIsSet(opcode, 23);
6387 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
6388
6389 // if wback && n == t then UNPREDICTABLE;
6390 if (wback && (n == t))
6391 return false;
6392
6393 break;
6394
6395 default:
6396 return false;
6397 }
6398
6399 addr_t address;
6400 addr_t offset_addr;
6401 addr_t base_address = ReadCoreReg(n, &success);
6402 if (!success)
6403 return false;
6404
6405 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6406 if (add)
6407 offset_addr = base_address + imm32;
6408 else
6409 offset_addr = base_address - imm32;
6410
6411 // address = if index then offset_addr else R[n];
6412 if (index)
6413 address = offset_addr;
6414 else
6415 address = base_address;
6416
6417 // data = MemU[address,4];
6418
6419 RegisterInfo base_reg;
6420 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6421
6422 EmulateInstruction::Context context;
6423 context.type = eContextRegisterLoad;
6424 context.SetRegisterPlusOffset(base_reg, address - base_address);
6425
6426 uint64_t data = MemURead(context, address, addr_byte_size, 0, &success);
6427 if (!success)
6428 return false;
6429
6430 // if wback then R[n] = offset_addr;
6431 if (wback) {
6432 context.type = eContextAdjustBaseRegister;
6433 context.SetAddress(offset_addr);
6434 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6435 offset_addr))
6436 return false;
6437 }
6438
6439 // if t == 15 then
6440 if (t == 15) {
6441 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6442 if (BitIsClear(address, 1) && BitIsClear(address, 0)) {
6443 // LoadWritePC (data);
6444 context.type = eContextRegisterLoad;
6445 context.SetRegisterPlusOffset(base_reg, address - base_address);
6446 LoadWritePC(context, data);
6447 } else
6448 return false;
6449 }
6450 // elsif UnalignedSupport() || address<1:0> = '00' then
6451 else if (UnalignedSupport() ||
6452 (BitIsClear(address, 1) && BitIsClear(address, 0))) {
6453 // R[t] = data;
6454 context.type = eContextRegisterLoad;
6455 context.SetRegisterPlusOffset(base_reg, address - base_address);
6456 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6457 data))
6458 return false;
6459 }
6460 // else // Can only apply before ARMv7
6461 else {
6462 // R[t] = ROR(data, 8*UInt(address<1:0>));
6463 data = ROR(data, Bits32(address, 1, 0), &success);
6464 if (!success)
6465 return false;
6466 context.type = eContextRegisterLoad;
6467 context.SetImmediate(data);
6468 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6469 data))
6470 return false;
6471 }
6472 }
6473 return true;
6474 }
6475
6476 // LDR (register) calculates an address from a base register value and an offset
6477 // register value, loads a word
6478 // from memory, and writes it to a register. The offset register value can
6479 // optionally be shifted.
EmulateLDRRegister(const uint32_t opcode,const ARMEncoding encoding)6480 bool EmulateInstructionARM::EmulateLDRRegister(const uint32_t opcode,
6481 const ARMEncoding encoding) {
6482 #if 0
6483 if ConditionPassed() then
6484 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6485 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6486 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6487 address = if index then offset_addr else R[n];
6488 data = MemU[address,4];
6489 if wback then R[n] = offset_addr;
6490 if t == 15 then
6491 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6492 elsif UnalignedSupport() || address<1:0> = '00' then
6493 R[t] = data;
6494 else // Can only apply before ARMv7
6495 if CurrentInstrSet() == InstrSet_ARM then
6496 R[t] = ROR(data, 8*UInt(address<1:0>));
6497 else
6498 R[t] = bits(32) UNKNOWN;
6499 #endif
6500
6501 bool success = false;
6502
6503 if (ConditionPassed(opcode)) {
6504 const uint32_t addr_byte_size = GetAddressByteSize();
6505
6506 uint32_t t;
6507 uint32_t n;
6508 uint32_t m;
6509 bool index;
6510 bool add;
6511 bool wback;
6512 ARM_ShifterType shift_t;
6513 uint32_t shift_n;
6514
6515 switch (encoding) {
6516 case eEncodingT1:
6517 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
6518 // in ThumbEE";
6519 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6520 t = Bits32(opcode, 2, 0);
6521 n = Bits32(opcode, 5, 3);
6522 m = Bits32(opcode, 8, 6);
6523
6524 // index = TRUE; add = TRUE; wback = FALSE;
6525 index = true;
6526 add = true;
6527 wback = false;
6528
6529 // (shift_t, shift_n) = (SRType_LSL, 0);
6530 shift_t = SRType_LSL;
6531 shift_n = 0;
6532
6533 break;
6534
6535 case eEncodingT2:
6536 // if Rn == '1111' then SEE LDR (literal);
6537 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6538 t = Bits32(opcode, 15, 12);
6539 n = Bits32(opcode, 19, 16);
6540 m = Bits32(opcode, 3, 0);
6541
6542 // index = TRUE; add = TRUE; wback = FALSE;
6543 index = true;
6544 add = true;
6545 wback = false;
6546
6547 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6548 shift_t = SRType_LSL;
6549 shift_n = Bits32(opcode, 5, 4);
6550
6551 // if BadReg(m) then UNPREDICTABLE;
6552 if (BadReg(m))
6553 return false;
6554
6555 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
6556 if ((t == 15) && InITBlock() && !LastInITBlock())
6557 return false;
6558
6559 break;
6560
6561 case eEncodingA1: {
6562 // if P == '0' && W == '1' then SEE LDRT;
6563 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6564 t = Bits32(opcode, 15, 12);
6565 n = Bits32(opcode, 19, 16);
6566 m = Bits32(opcode, 3, 0);
6567
6568 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6569 // (W == '1');
6570 index = BitIsSet(opcode, 24);
6571 add = BitIsSet(opcode, 23);
6572 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
6573
6574 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6575 uint32_t type = Bits32(opcode, 6, 5);
6576 uint32_t imm5 = Bits32(opcode, 11, 7);
6577 shift_n = DecodeImmShift(type, imm5, shift_t);
6578
6579 // if m == 15 then UNPREDICTABLE;
6580 if (m == 15)
6581 return false;
6582
6583 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6584 if (wback && ((n == 15) || (n == t)))
6585 return false;
6586 } break;
6587
6588 default:
6589 return false;
6590 }
6591
6592 uint32_t Rm =
6593 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6594 if (!success)
6595 return false;
6596
6597 uint32_t Rn =
6598 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6599 if (!success)
6600 return false;
6601
6602 addr_t offset_addr;
6603 addr_t address;
6604
6605 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is
6606 // an application level alias for the CPSR".
6607 addr_t offset =
6608 Shift(Rm, shift_t, shift_n, Bit32(m_opcode_cpsr, APSR_C), &success);
6609 if (!success)
6610 return false;
6611
6612 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6613 if (add)
6614 offset_addr = Rn + offset;
6615 else
6616 offset_addr = Rn - offset;
6617
6618 // address = if index then offset_addr else R[n];
6619 if (index)
6620 address = offset_addr;
6621 else
6622 address = Rn;
6623
6624 // data = MemU[address,4];
6625 RegisterInfo base_reg;
6626 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6627
6628 EmulateInstruction::Context context;
6629 context.type = eContextRegisterLoad;
6630 context.SetRegisterPlusOffset(base_reg, address - Rn);
6631
6632 uint64_t data = MemURead(context, address, addr_byte_size, 0, &success);
6633 if (!success)
6634 return false;
6635
6636 // if wback then R[n] = offset_addr;
6637 if (wback) {
6638 context.type = eContextAdjustBaseRegister;
6639 context.SetAddress(offset_addr);
6640 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6641 offset_addr))
6642 return false;
6643 }
6644
6645 // if t == 15 then
6646 if (t == 15) {
6647 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6648 if (BitIsClear(address, 1) && BitIsClear(address, 0)) {
6649 context.type = eContextRegisterLoad;
6650 context.SetRegisterPlusOffset(base_reg, address - Rn);
6651 LoadWritePC(context, data);
6652 } else
6653 return false;
6654 }
6655 // elsif UnalignedSupport() || address<1:0> = '00' then
6656 else if (UnalignedSupport() ||
6657 (BitIsClear(address, 1) && BitIsClear(address, 0))) {
6658 // R[t] = data;
6659 context.type = eContextRegisterLoad;
6660 context.SetRegisterPlusOffset(base_reg, address - Rn);
6661 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6662 data))
6663 return false;
6664 } else // Can only apply before ARMv7
6665 {
6666 // if CurrentInstrSet() == InstrSet_ARM then
6667 if (CurrentInstrSet() == eModeARM) {
6668 // R[t] = ROR(data, 8*UInt(address<1:0>));
6669 data = ROR(data, Bits32(address, 1, 0), &success);
6670 if (!success)
6671 return false;
6672 context.type = eContextRegisterLoad;
6673 context.SetImmediate(data);
6674 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6675 data))
6676 return false;
6677 } else {
6678 // R[t] = bits(32) UNKNOWN;
6679 WriteBits32Unknown(t);
6680 }
6681 }
6682 }
6683 return true;
6684 }
6685
6686 // LDRB (immediate, Thumb)
EmulateLDRBImmediate(const uint32_t opcode,const ARMEncoding encoding)6687 bool EmulateInstructionARM::EmulateLDRBImmediate(const uint32_t opcode,
6688 const ARMEncoding encoding) {
6689 #if 0
6690 if ConditionPassed() then
6691 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6692 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6693 address = if index then offset_addr else R[n];
6694 R[t] = ZeroExtend(MemU[address,1], 32);
6695 if wback then R[n] = offset_addr;
6696 #endif
6697
6698 bool success = false;
6699
6700 if (ConditionPassed(opcode)) {
6701 uint32_t t;
6702 uint32_t n;
6703 uint32_t imm32;
6704 bool index;
6705 bool add;
6706 bool wback;
6707
6708 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6709 switch (encoding) {
6710 case eEncodingT1:
6711 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6712 t = Bits32(opcode, 2, 0);
6713 n = Bits32(opcode, 5, 3);
6714 imm32 = Bits32(opcode, 10, 6);
6715
6716 // index = TRUE; add = TRUE; wback = FALSE;
6717 index = true;
6718 add = true;
6719 wback = false;
6720
6721 break;
6722
6723 case eEncodingT2:
6724 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6725 t = Bits32(opcode, 15, 12);
6726 n = Bits32(opcode, 19, 16);
6727 imm32 = Bits32(opcode, 11, 0);
6728
6729 // index = TRUE; add = TRUE; wback = FALSE;
6730 index = true;
6731 add = true;
6732 wback = false;
6733
6734 // if Rt == '1111' then SEE PLD;
6735 if (t == 15)
6736 return false; // PLD is not implemented yet
6737
6738 // if Rn == '1111' then SEE LDRB (literal);
6739 if (n == 15)
6740 return EmulateLDRBLiteral(opcode, eEncodingT1);
6741
6742 // if t == 13 then UNPREDICTABLE;
6743 if (t == 13)
6744 return false;
6745
6746 break;
6747
6748 case eEncodingT3:
6749 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
6750 // if P == '0' && W == '0' then UNDEFINED;
6751 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
6752 return false;
6753
6754 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6755 t = Bits32(opcode, 15, 12);
6756 n = Bits32(opcode, 19, 16);
6757 imm32 = Bits32(opcode, 7, 0);
6758
6759 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
6760 index = BitIsSet(opcode, 10);
6761 add = BitIsSet(opcode, 9);
6762 wback = BitIsSet(opcode, 8);
6763
6764 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
6765 if (t == 15)
6766 return false; // PLD is not implemented yet
6767
6768 // if Rn == '1111' then SEE LDRB (literal);
6769 if (n == 15)
6770 return EmulateLDRBLiteral(opcode, eEncodingT1);
6771
6772 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6773 if (BadReg(t) || (wback && (n == t)))
6774 return false;
6775
6776 break;
6777
6778 default:
6779 return false;
6780 }
6781
6782 uint32_t Rn =
6783 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6784 if (!success)
6785 return false;
6786
6787 addr_t address;
6788 addr_t offset_addr;
6789
6790 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6791 if (add)
6792 offset_addr = Rn + imm32;
6793 else
6794 offset_addr = Rn - imm32;
6795
6796 // address = if index then offset_addr else R[n];
6797 if (index)
6798 address = offset_addr;
6799 else
6800 address = Rn;
6801
6802 // R[t] = ZeroExtend(MemU[address,1], 32);
6803 RegisterInfo base_reg;
6804 RegisterInfo data_reg;
6805 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6806 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
6807
6808 EmulateInstruction::Context context;
6809 context.type = eContextRegisterLoad;
6810 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
6811
6812 uint64_t data = MemURead(context, address, 1, 0, &success);
6813 if (!success)
6814 return false;
6815
6816 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
6817 return false;
6818
6819 // if wback then R[n] = offset_addr;
6820 if (wback) {
6821 context.type = eContextAdjustBaseRegister;
6822 context.SetAddress(offset_addr);
6823 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6824 offset_addr))
6825 return false;
6826 }
6827 }
6828 return true;
6829 }
6830
6831 // LDRB (literal) calculates an address from the PC value and an immediate
6832 // offset, loads a byte from memory,
6833 // zero-extends it to form a 32-bit word and writes it to a register.
EmulateLDRBLiteral(const uint32_t opcode,const ARMEncoding encoding)6834 bool EmulateInstructionARM::EmulateLDRBLiteral(const uint32_t opcode,
6835 const ARMEncoding encoding) {
6836 #if 0
6837 if ConditionPassed() then
6838 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6839 base = Align(PC,4);
6840 address = if add then (base + imm32) else (base - imm32);
6841 R[t] = ZeroExtend(MemU[address,1], 32);
6842 #endif
6843
6844 bool success = false;
6845
6846 if (ConditionPassed(opcode)) {
6847 uint32_t t;
6848 uint32_t imm32;
6849 bool add;
6850 switch (encoding) {
6851 case eEncodingT1:
6852 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6853 t = Bits32(opcode, 15, 12);
6854 imm32 = Bits32(opcode, 11, 0);
6855 add = BitIsSet(opcode, 23);
6856
6857 // if Rt == '1111' then SEE PLD;
6858 if (t == 15)
6859 return false; // PLD is not implemented yet
6860
6861 // if t == 13 then UNPREDICTABLE;
6862 if (t == 13)
6863 return false;
6864
6865 break;
6866
6867 case eEncodingA1:
6868 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6869 t = Bits32(opcode, 15, 12);
6870 imm32 = Bits32(opcode, 11, 0);
6871 add = BitIsSet(opcode, 23);
6872
6873 // if t == 15 then UNPREDICTABLE;
6874 if (t == 15)
6875 return false;
6876 break;
6877
6878 default:
6879 return false;
6880 }
6881
6882 // base = Align(PC,4);
6883 uint32_t pc_val = ReadCoreReg(PC_REG, &success);
6884 if (!success)
6885 return false;
6886
6887 uint32_t base = AlignPC(pc_val);
6888
6889 addr_t address;
6890 // address = if add then (base + imm32) else (base - imm32);
6891 if (add)
6892 address = base + imm32;
6893 else
6894 address = base - imm32;
6895
6896 // R[t] = ZeroExtend(MemU[address,1], 32);
6897 EmulateInstruction::Context context;
6898 context.type = eContextRelativeBranchImmediate;
6899 context.SetImmediate(address - base);
6900
6901 uint64_t data = MemURead(context, address, 1, 0, &success);
6902 if (!success)
6903 return false;
6904
6905 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
6906 return false;
6907 }
6908 return true;
6909 }
6910
6911 // LDRB (register) calculates an address from a base register value and an
6912 // offset rigister value, loads a byte from memory, zero-extends it to form a
6913 // 32-bit word, and writes it to a register. The offset register value can
6914 // optionally be shifted.
EmulateLDRBRegister(const uint32_t opcode,const ARMEncoding encoding)6915 bool EmulateInstructionARM::EmulateLDRBRegister(const uint32_t opcode,
6916 const ARMEncoding encoding) {
6917 #if 0
6918 if ConditionPassed() then
6919 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6920 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6921 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6922 address = if index then offset_addr else R[n];
6923 R[t] = ZeroExtend(MemU[address,1],32);
6924 if wback then R[n] = offset_addr;
6925 #endif
6926
6927 bool success = false;
6928
6929 if (ConditionPassed(opcode)) {
6930 uint32_t t;
6931 uint32_t n;
6932 uint32_t m;
6933 bool index;
6934 bool add;
6935 bool wback;
6936 ARM_ShifterType shift_t;
6937 uint32_t shift_n;
6938
6939 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6940 switch (encoding) {
6941 case eEncodingT1:
6942 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6943 t = Bits32(opcode, 2, 0);
6944 n = Bits32(opcode, 5, 3);
6945 m = Bits32(opcode, 8, 6);
6946
6947 // index = TRUE; add = TRUE; wback = FALSE;
6948 index = true;
6949 add = true;
6950 wback = false;
6951
6952 // (shift_t, shift_n) = (SRType_LSL, 0);
6953 shift_t = SRType_LSL;
6954 shift_n = 0;
6955 break;
6956
6957 case eEncodingT2:
6958 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6959 t = Bits32(opcode, 15, 12);
6960 n = Bits32(opcode, 19, 16);
6961 m = Bits32(opcode, 3, 0);
6962
6963 // index = TRUE; add = TRUE; wback = FALSE;
6964 index = true;
6965 add = true;
6966 wback = false;
6967
6968 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6969 shift_t = SRType_LSL;
6970 shift_n = Bits32(opcode, 5, 4);
6971
6972 // if Rt == '1111' then SEE PLD;
6973 if (t == 15)
6974 return false; // PLD is not implemented yet
6975
6976 // if Rn == '1111' then SEE LDRB (literal);
6977 if (n == 15)
6978 return EmulateLDRBLiteral(opcode, eEncodingT1);
6979
6980 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6981 if ((t == 13) || BadReg(m))
6982 return false;
6983 break;
6984
6985 case eEncodingA1: {
6986 // if P == '0' && W == '1' then SEE LDRBT;
6987 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6988 t = Bits32(opcode, 15, 12);
6989 n = Bits32(opcode, 19, 16);
6990 m = Bits32(opcode, 3, 0);
6991
6992 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6993 // (W == '1');
6994 index = BitIsSet(opcode, 24);
6995 add = BitIsSet(opcode, 23);
6996 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
6997
6998 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6999 uint32_t type = Bits32(opcode, 6, 5);
7000 uint32_t imm5 = Bits32(opcode, 11, 7);
7001 shift_n = DecodeImmShift(type, imm5, shift_t);
7002
7003 // if t == 15 || m == 15 then UNPREDICTABLE;
7004 if ((t == 15) || (m == 15))
7005 return false;
7006
7007 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7008 if (wback && ((n == 15) || (n == t)))
7009 return false;
7010 } break;
7011
7012 default:
7013 return false;
7014 }
7015
7016 addr_t offset_addr;
7017 addr_t address;
7018
7019 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7020 uint32_t Rm =
7021 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7022 if (!success)
7023 return false;
7024
7025 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
7026 if (!success)
7027 return false;
7028
7029 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7030 uint32_t Rn =
7031 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7032 if (!success)
7033 return false;
7034
7035 if (add)
7036 offset_addr = Rn + offset;
7037 else
7038 offset_addr = Rn - offset;
7039
7040 // address = if index then offset_addr else R[n];
7041 if (index)
7042 address = offset_addr;
7043 else
7044 address = Rn;
7045
7046 // R[t] = ZeroExtend(MemU[address,1],32);
7047 RegisterInfo base_reg;
7048 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7049
7050 EmulateInstruction::Context context;
7051 context.type = eContextRegisterLoad;
7052 context.SetRegisterPlusOffset(base_reg, address - Rn);
7053
7054 uint64_t data = MemURead(context, address, 1, 0, &success);
7055 if (!success)
7056 return false;
7057
7058 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
7059 return false;
7060
7061 // if wback then R[n] = offset_addr;
7062 if (wback) {
7063 context.type = eContextAdjustBaseRegister;
7064 context.SetAddress(offset_addr);
7065 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7066 offset_addr))
7067 return false;
7068 }
7069 }
7070 return true;
7071 }
7072
7073 // LDRH (immediate, Thumb) calculates an address from a base register value and
7074 // an immediate offset, loads a
7075 // halfword from memory, zero-extends it to form a 32-bit word, and writes it
7076 // to a register. It can use offset, post-indexed, or pre-indexed addressing.
EmulateLDRHImmediate(const uint32_t opcode,const ARMEncoding encoding)7077 bool EmulateInstructionARM::EmulateLDRHImmediate(const uint32_t opcode,
7078 const ARMEncoding encoding) {
7079 #if 0
7080 if ConditionPassed() then
7081 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7082 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7083 address = if index then offset_addr else R[n];
7084 data = MemU[address,2];
7085 if wback then R[n] = offset_addr;
7086 if UnalignedSupport() || address<0> = '0' then
7087 R[t] = ZeroExtend(data, 32);
7088 else // Can only apply before ARMv7
7089 R[t] = bits(32) UNKNOWN;
7090 #endif
7091
7092 bool success = false;
7093
7094 if (ConditionPassed(opcode)) {
7095 uint32_t t;
7096 uint32_t n;
7097 uint32_t imm32;
7098 bool index;
7099 bool add;
7100 bool wback;
7101
7102 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7103 switch (encoding) {
7104 case eEncodingT1:
7105 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
7106 t = Bits32(opcode, 2, 0);
7107 n = Bits32(opcode, 5, 3);
7108 imm32 = Bits32(opcode, 10, 6) << 1;
7109
7110 // index = TRUE; add = TRUE; wback = FALSE;
7111 index = true;
7112 add = true;
7113 wback = false;
7114
7115 break;
7116
7117 case eEncodingT2:
7118 // if Rt == '1111' then SEE "Unallocated memory hints";
7119 // if Rn == '1111' then SEE LDRH (literal);
7120 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7121 t = Bits32(opcode, 15, 12);
7122 n = Bits32(opcode, 19, 16);
7123 imm32 = Bits32(opcode, 11, 0);
7124
7125 // index = TRUE; add = TRUE; wback = FALSE;
7126 index = true;
7127 add = true;
7128 wback = false;
7129
7130 // if t == 13 then UNPREDICTABLE;
7131 if (t == 13)
7132 return false;
7133 break;
7134
7135 case eEncodingT3:
7136 // if Rn == '1111' then SEE LDRH (literal);
7137 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE
7138 // "Unallocated memory hints";
7139 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
7140 // if P == '0' && W == '0' then UNDEFINED;
7141 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
7142 return false;
7143
7144 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7145 t = Bits32(opcode, 15, 12);
7146 n = Bits32(opcode, 19, 16);
7147 imm32 = Bits32(opcode, 7, 0);
7148
7149 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7150 index = BitIsSet(opcode, 10);
7151 add = BitIsSet(opcode, 9);
7152 wback = BitIsSet(opcode, 8);
7153
7154 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7155 if (BadReg(t) || (wback && (n == t)))
7156 return false;
7157 break;
7158
7159 default:
7160 return false;
7161 }
7162
7163 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7164 uint32_t Rn =
7165 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7166 if (!success)
7167 return false;
7168
7169 addr_t offset_addr;
7170 addr_t address;
7171
7172 if (add)
7173 offset_addr = Rn + imm32;
7174 else
7175 offset_addr = Rn - imm32;
7176
7177 // address = if index then offset_addr else R[n];
7178 if (index)
7179 address = offset_addr;
7180 else
7181 address = Rn;
7182
7183 // data = MemU[address,2];
7184 RegisterInfo base_reg;
7185 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7186
7187 EmulateInstruction::Context context;
7188 context.type = eContextRegisterLoad;
7189 context.SetRegisterPlusOffset(base_reg, address - Rn);
7190
7191 uint64_t data = MemURead(context, address, 2, 0, &success);
7192 if (!success)
7193 return false;
7194
7195 // if wback then R[n] = offset_addr;
7196 if (wback) {
7197 context.type = eContextAdjustBaseRegister;
7198 context.SetAddress(offset_addr);
7199 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7200 offset_addr))
7201 return false;
7202 }
7203
7204 // if UnalignedSupport() || address<0> = '0' then
7205 if (UnalignedSupport() || BitIsClear(address, 0)) {
7206 // R[t] = ZeroExtend(data, 32);
7207 context.type = eContextRegisterLoad;
7208 context.SetRegisterPlusOffset(base_reg, address - Rn);
7209 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7210 data))
7211 return false;
7212 } else // Can only apply before ARMv7
7213 {
7214 // R[t] = bits(32) UNKNOWN;
7215 WriteBits32Unknown(t);
7216 }
7217 }
7218 return true;
7219 }
7220
7221 // LDRH (literal) calculates an address from the PC value and an immediate
7222 // offset, loads a halfword from memory,
7223 // zero-extends it to form a 32-bit word, and writes it to a register.
EmulateLDRHLiteral(const uint32_t opcode,const ARMEncoding encoding)7224 bool EmulateInstructionARM::EmulateLDRHLiteral(const uint32_t opcode,
7225 const ARMEncoding encoding) {
7226 #if 0
7227 if ConditionPassed() then
7228 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7229 base = Align(PC,4);
7230 address = if add then (base + imm32) else (base - imm32);
7231 data = MemU[address,2];
7232 if UnalignedSupport() || address<0> = '0' then
7233 R[t] = ZeroExtend(data, 32);
7234 else // Can only apply before ARMv7
7235 R[t] = bits(32) UNKNOWN;
7236 #endif
7237
7238 bool success = false;
7239
7240 if (ConditionPassed(opcode)) {
7241 uint32_t t;
7242 uint32_t imm32;
7243 bool add;
7244
7245 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7246 switch (encoding) {
7247 case eEncodingT1:
7248 // if Rt == '1111' then SEE "Unallocated memory hints";
7249 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
7250 t = Bits32(opcode, 15, 12);
7251 imm32 = Bits32(opcode, 11, 0);
7252 add = BitIsSet(opcode, 23);
7253
7254 // if t == 13 then UNPREDICTABLE;
7255 if (t == 13)
7256 return false;
7257
7258 break;
7259
7260 case eEncodingA1: {
7261 uint32_t imm4H = Bits32(opcode, 11, 8);
7262 uint32_t imm4L = Bits32(opcode, 3, 0);
7263
7264 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7265 t = Bits32(opcode, 15, 12);
7266 imm32 = (imm4H << 4) | imm4L;
7267 add = BitIsSet(opcode, 23);
7268
7269 // if t == 15 then UNPREDICTABLE;
7270 if (t == 15)
7271 return false;
7272 break;
7273 }
7274
7275 default:
7276 return false;
7277 }
7278
7279 // base = Align(PC,4);
7280 uint64_t pc_value = ReadCoreReg(PC_REG, &success);
7281 if (!success)
7282 return false;
7283
7284 addr_t base = AlignPC(pc_value);
7285 addr_t address;
7286
7287 // address = if add then (base + imm32) else (base - imm32);
7288 if (add)
7289 address = base + imm32;
7290 else
7291 address = base - imm32;
7292
7293 // data = MemU[address,2];
7294 RegisterInfo base_reg;
7295 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
7296
7297 EmulateInstruction::Context context;
7298 context.type = eContextRegisterLoad;
7299 context.SetRegisterPlusOffset(base_reg, address - base);
7300
7301 uint64_t data = MemURead(context, address, 2, 0, &success);
7302 if (!success)
7303 return false;
7304
7305 // if UnalignedSupport() || address<0> = '0' then
7306 if (UnalignedSupport() || BitIsClear(address, 0)) {
7307 // R[t] = ZeroExtend(data, 32);
7308 context.type = eContextRegisterLoad;
7309 context.SetRegisterPlusOffset(base_reg, address - base);
7310 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7311 data))
7312 return false;
7313
7314 } else // Can only apply before ARMv7
7315 {
7316 // R[t] = bits(32) UNKNOWN;
7317 WriteBits32Unknown(t);
7318 }
7319 }
7320 return true;
7321 }
7322
7323 // LDRH (literal) calculates an address from a base register value and an offset
7324 // register value, loads a halfword
7325 // from memory, zero-extends it to form a 32-bit word, and writes it to a
7326 // register. The offset register value can be shifted left by 0, 1, 2, or 3
7327 // bits.
EmulateLDRHRegister(const uint32_t opcode,const ARMEncoding encoding)7328 bool EmulateInstructionARM::EmulateLDRHRegister(const uint32_t opcode,
7329 const ARMEncoding encoding) {
7330 #if 0
7331 if ConditionPassed() then
7332 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7333 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7334 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7335 address = if index then offset_addr else R[n];
7336 data = MemU[address,2];
7337 if wback then R[n] = offset_addr;
7338 if UnalignedSupport() || address<0> = '0' then
7339 R[t] = ZeroExtend(data, 32);
7340 else // Can only apply before ARMv7
7341 R[t] = bits(32) UNKNOWN;
7342 #endif
7343
7344 bool success = false;
7345
7346 if (ConditionPassed(opcode)) {
7347 uint32_t t;
7348 uint32_t n;
7349 uint32_t m;
7350 bool index;
7351 bool add;
7352 bool wback;
7353 ARM_ShifterType shift_t;
7354 uint32_t shift_n;
7355
7356 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7357 switch (encoding) {
7358 case eEncodingT1:
7359 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
7360 // in ThumbEE";
7361 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7362 t = Bits32(opcode, 2, 0);
7363 n = Bits32(opcode, 5, 3);
7364 m = Bits32(opcode, 8, 6);
7365
7366 // index = TRUE; add = TRUE; wback = FALSE;
7367 index = true;
7368 add = true;
7369 wback = false;
7370
7371 // (shift_t, shift_n) = (SRType_LSL, 0);
7372 shift_t = SRType_LSL;
7373 shift_n = 0;
7374
7375 break;
7376
7377 case eEncodingT2:
7378 // if Rn == '1111' then SEE LDRH (literal);
7379 // if Rt == '1111' then SEE "Unallocated memory hints";
7380 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7381 t = Bits32(opcode, 15, 12);
7382 n = Bits32(opcode, 19, 16);
7383 m = Bits32(opcode, 3, 0);
7384
7385 // index = TRUE; add = TRUE; wback = FALSE;
7386 index = true;
7387 add = true;
7388 wback = false;
7389
7390 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7391 shift_t = SRType_LSL;
7392 shift_n = Bits32(opcode, 5, 4);
7393
7394 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7395 if ((t == 13) || BadReg(m))
7396 return false;
7397 break;
7398
7399 case eEncodingA1:
7400 // if P == '0' && W == '1' then SEE LDRHT;
7401 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7402 t = Bits32(opcode, 15, 12);
7403 n = Bits32(opcode, 19, 16);
7404 m = Bits32(opcode, 3, 0);
7405
7406 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7407 // (W == '1');
7408 index = BitIsSet(opcode, 24);
7409 add = BitIsSet(opcode, 23);
7410 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
7411
7412 // (shift_t, shift_n) = (SRType_LSL, 0);
7413 shift_t = SRType_LSL;
7414 shift_n = 0;
7415
7416 // if t == 15 || m == 15 then UNPREDICTABLE;
7417 if ((t == 15) || (m == 15))
7418 return false;
7419
7420 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7421 if (wback && ((n == 15) || (n == t)))
7422 return false;
7423
7424 break;
7425
7426 default:
7427 return false;
7428 }
7429
7430 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7431
7432 uint64_t Rm =
7433 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7434 if (!success)
7435 return false;
7436
7437 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
7438 if (!success)
7439 return false;
7440
7441 addr_t offset_addr;
7442 addr_t address;
7443
7444 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7445 uint64_t Rn =
7446 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7447 if (!success)
7448 return false;
7449
7450 if (add)
7451 offset_addr = Rn + offset;
7452 else
7453 offset_addr = Rn - offset;
7454
7455 // address = if index then offset_addr else R[n];
7456 if (index)
7457 address = offset_addr;
7458 else
7459 address = Rn;
7460
7461 // data = MemU[address,2];
7462 RegisterInfo base_reg;
7463 RegisterInfo offset_reg;
7464 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7465 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
7466
7467 EmulateInstruction::Context context;
7468 context.type = eContextRegisterLoad;
7469 context.SetRegisterPlusIndirectOffset(base_reg, offset_reg);
7470 uint64_t data = MemURead(context, address, 2, 0, &success);
7471 if (!success)
7472 return false;
7473
7474 // if wback then R[n] = offset_addr;
7475 if (wback) {
7476 context.type = eContextAdjustBaseRegister;
7477 context.SetAddress(offset_addr);
7478 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7479 offset_addr))
7480 return false;
7481 }
7482
7483 // if UnalignedSupport() || address<0> = '0' then
7484 if (UnalignedSupport() || BitIsClear(address, 0)) {
7485 // R[t] = ZeroExtend(data, 32);
7486 context.type = eContextRegisterLoad;
7487 context.SetRegisterPlusIndirectOffset(base_reg, offset_reg);
7488 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7489 data))
7490 return false;
7491 } else // Can only apply before ARMv7
7492 {
7493 // R[t] = bits(32) UNKNOWN;
7494 WriteBits32Unknown(t);
7495 }
7496 }
7497 return true;
7498 }
7499
7500 // LDRSB (immediate) calculates an address from a base register value and an
7501 // immediate offset, loads a byte from
7502 // memory, sign-extends it to form a 32-bit word, and writes it to a register.
7503 // It can use offset, post-indexed, or pre-indexed addressing.
EmulateLDRSBImmediate(const uint32_t opcode,const ARMEncoding encoding)7504 bool EmulateInstructionARM::EmulateLDRSBImmediate(const uint32_t opcode,
7505 const ARMEncoding encoding) {
7506 #if 0
7507 if ConditionPassed() then
7508 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7509 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7510 address = if index then offset_addr else R[n];
7511 R[t] = SignExtend(MemU[address,1], 32);
7512 if wback then R[n] = offset_addr;
7513 #endif
7514
7515 bool success = false;
7516
7517 if (ConditionPassed(opcode)) {
7518 uint32_t t;
7519 uint32_t n;
7520 uint32_t imm32;
7521 bool index;
7522 bool add;
7523 bool wback;
7524
7525 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7526 switch (encoding) {
7527 case eEncodingT1:
7528 // if Rt == '1111' then SEE PLI;
7529 // if Rn == '1111' then SEE LDRSB (literal);
7530 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7531 t = Bits32(opcode, 15, 12);
7532 n = Bits32(opcode, 19, 16);
7533 imm32 = Bits32(opcode, 11, 0);
7534
7535 // index = TRUE; add = TRUE; wback = FALSE;
7536 index = true;
7537 add = true;
7538 wback = false;
7539
7540 // if t == 13 then UNPREDICTABLE;
7541 if (t == 13)
7542 return false;
7543
7544 break;
7545
7546 case eEncodingT2:
7547 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
7548 // if Rn == '1111' then SEE LDRSB (literal);
7549 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
7550 // if P == '0' && W == '0' then UNDEFINED;
7551 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
7552 return false;
7553
7554 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7555 t = Bits32(opcode, 15, 12);
7556 n = Bits32(opcode, 19, 16);
7557 imm32 = Bits32(opcode, 7, 0);
7558
7559 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7560 index = BitIsSet(opcode, 10);
7561 add = BitIsSet(opcode, 9);
7562 wback = BitIsSet(opcode, 8);
7563
7564 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7565 if (((t == 13) ||
7566 ((t == 15) && (BitIsClear(opcode, 10) || BitIsSet(opcode, 9) ||
7567 BitIsSet(opcode, 8)))) ||
7568 (wback && (n == t)))
7569 return false;
7570
7571 break;
7572
7573 case eEncodingA1: {
7574 // if Rn == '1111' then SEE LDRSB (literal);
7575 // if P == '0' && W == '1' then SEE LDRSBT;
7576 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7577 t = Bits32(opcode, 15, 12);
7578 n = Bits32(opcode, 19, 16);
7579
7580 uint32_t imm4H = Bits32(opcode, 11, 8);
7581 uint32_t imm4L = Bits32(opcode, 3, 0);
7582 imm32 = (imm4H << 4) | imm4L;
7583
7584 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7585 // (W == '1');
7586 index = BitIsSet(opcode, 24);
7587 add = BitIsSet(opcode, 23);
7588 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
7589
7590 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7591 if ((t == 15) || (wback && (n == t)))
7592 return false;
7593
7594 break;
7595 }
7596
7597 default:
7598 return false;
7599 }
7600
7601 uint64_t Rn = ReadCoreReg(n, &success);
7602 if (!success)
7603 return false;
7604
7605 addr_t offset_addr;
7606 addr_t address;
7607
7608 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7609 if (add)
7610 offset_addr = Rn + imm32;
7611 else
7612 offset_addr = Rn - imm32;
7613
7614 // address = if index then offset_addr else R[n];
7615 if (index)
7616 address = offset_addr;
7617 else
7618 address = Rn;
7619
7620 // R[t] = SignExtend(MemU[address,1], 32);
7621 RegisterInfo base_reg;
7622 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7623
7624 EmulateInstruction::Context context;
7625 context.type = eContextRegisterLoad;
7626 context.SetRegisterPlusOffset(base_reg, address - Rn);
7627
7628 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);
7629 if (!success)
7630 return false;
7631
7632 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7633 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7634 (uint64_t)signed_data))
7635 return false;
7636
7637 // if wback then R[n] = offset_addr;
7638 if (wback) {
7639 context.type = eContextAdjustBaseRegister;
7640 context.SetAddress(offset_addr);
7641 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7642 offset_addr))
7643 return false;
7644 }
7645 }
7646
7647 return true;
7648 }
7649
7650 // LDRSB (literal) calculates an address from the PC value and an immediate
7651 // offset, loads a byte from memory,
7652 // sign-extends it to form a 32-bit word, and writes tit to a register.
EmulateLDRSBLiteral(const uint32_t opcode,const ARMEncoding encoding)7653 bool EmulateInstructionARM::EmulateLDRSBLiteral(const uint32_t opcode,
7654 const ARMEncoding encoding) {
7655 #if 0
7656 if ConditionPassed() then
7657 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7658 base = Align(PC,4);
7659 address = if add then (base + imm32) else (base - imm32);
7660 R[t] = SignExtend(MemU[address,1], 32);
7661 #endif
7662
7663 bool success = false;
7664
7665 if (ConditionPassed(opcode)) {
7666 uint32_t t;
7667 uint32_t imm32;
7668 bool add;
7669
7670 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7671 switch (encoding) {
7672 case eEncodingT1:
7673 // if Rt == '1111' then SEE PLI;
7674 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
7675 t = Bits32(opcode, 15, 12);
7676 imm32 = Bits32(opcode, 11, 0);
7677 add = BitIsSet(opcode, 23);
7678
7679 // if t == 13 then UNPREDICTABLE;
7680 if (t == 13)
7681 return false;
7682
7683 break;
7684
7685 case eEncodingA1: {
7686 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7687 t = Bits32(opcode, 15, 12);
7688 uint32_t imm4H = Bits32(opcode, 11, 8);
7689 uint32_t imm4L = Bits32(opcode, 3, 0);
7690 imm32 = (imm4H << 4) | imm4L;
7691 add = BitIsSet(opcode, 23);
7692
7693 // if t == 15 then UNPREDICTABLE;
7694 if (t == 15)
7695 return false;
7696
7697 break;
7698 }
7699
7700 default:
7701 return false;
7702 }
7703
7704 // base = Align(PC,4);
7705 uint64_t pc_value = ReadCoreReg(PC_REG, &success);
7706 if (!success)
7707 return false;
7708 uint64_t base = AlignPC(pc_value);
7709
7710 // address = if add then (base + imm32) else (base - imm32);
7711 addr_t address;
7712 if (add)
7713 address = base + imm32;
7714 else
7715 address = base - imm32;
7716
7717 // R[t] = SignExtend(MemU[address,1], 32);
7718 RegisterInfo base_reg;
7719 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
7720
7721 EmulateInstruction::Context context;
7722 context.type = eContextRegisterLoad;
7723 context.SetRegisterPlusOffset(base_reg, address - base);
7724
7725 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);
7726 if (!success)
7727 return false;
7728
7729 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7730 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7731 (uint64_t)signed_data))
7732 return false;
7733 }
7734 return true;
7735 }
7736
7737 // LDRSB (register) calculates an address from a base register value and an
7738 // offset register value, loadsa byte from
7739 // memory, sign-extends it to form a 32-bit word, and writes it to a register.
7740 // The offset register value can be shifted left by 0, 1, 2, or 3 bits.
EmulateLDRSBRegister(const uint32_t opcode,const ARMEncoding encoding)7741 bool EmulateInstructionARM::EmulateLDRSBRegister(const uint32_t opcode,
7742 const ARMEncoding encoding) {
7743 #if 0
7744 if ConditionPassed() then
7745 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7746 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7747 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7748 address = if index then offset_addr else R[n];
7749 R[t] = SignExtend(MemU[address,1], 32);
7750 if wback then R[n] = offset_addr;
7751 #endif
7752
7753 bool success = false;
7754
7755 if (ConditionPassed(opcode)) {
7756 uint32_t t;
7757 uint32_t n;
7758 uint32_t m;
7759 bool index;
7760 bool add;
7761 bool wback;
7762 ARM_ShifterType shift_t;
7763 uint32_t shift_n;
7764
7765 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7766 switch (encoding) {
7767 case eEncodingT1:
7768 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7769 t = Bits32(opcode, 2, 0);
7770 n = Bits32(opcode, 5, 3);
7771 m = Bits32(opcode, 8, 6);
7772
7773 // index = TRUE; add = TRUE; wback = FALSE;
7774 index = true;
7775 add = true;
7776 wback = false;
7777
7778 // (shift_t, shift_n) = (SRType_LSL, 0);
7779 shift_t = SRType_LSL;
7780 shift_n = 0;
7781
7782 break;
7783
7784 case eEncodingT2:
7785 // if Rt == '1111' then SEE PLI;
7786 // if Rn == '1111' then SEE LDRSB (literal);
7787 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7788 t = Bits32(opcode, 15, 12);
7789 n = Bits32(opcode, 19, 16);
7790 m = Bits32(opcode, 3, 0);
7791
7792 // index = TRUE; add = TRUE; wback = FALSE;
7793 index = true;
7794 add = true;
7795 wback = false;
7796
7797 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7798 shift_t = SRType_LSL;
7799 shift_n = Bits32(opcode, 5, 4);
7800
7801 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7802 if ((t == 13) || BadReg(m))
7803 return false;
7804 break;
7805
7806 case eEncodingA1:
7807 // if P == '0' && W == '1' then SEE LDRSBT;
7808 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7809 t = Bits32(opcode, 15, 12);
7810 n = Bits32(opcode, 19, 16);
7811 m = Bits32(opcode, 3, 0);
7812
7813 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7814 // (W == '1');
7815 index = BitIsSet(opcode, 24);
7816 add = BitIsSet(opcode, 23);
7817 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
7818
7819 // (shift_t, shift_n) = (SRType_LSL, 0);
7820 shift_t = SRType_LSL;
7821 shift_n = 0;
7822
7823 // if t == 15 || m == 15 then UNPREDICTABLE;
7824 if ((t == 15) || (m == 15))
7825 return false;
7826
7827 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7828 if (wback && ((n == 15) || (n == t)))
7829 return false;
7830 break;
7831
7832 default:
7833 return false;
7834 }
7835
7836 uint64_t Rm =
7837 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7838 if (!success)
7839 return false;
7840
7841 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7842 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
7843 if (!success)
7844 return false;
7845
7846 addr_t offset_addr;
7847 addr_t address;
7848
7849 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7850 uint64_t Rn =
7851 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7852 if (!success)
7853 return false;
7854
7855 if (add)
7856 offset_addr = Rn + offset;
7857 else
7858 offset_addr = Rn - offset;
7859
7860 // address = if index then offset_addr else R[n];
7861 if (index)
7862 address = offset_addr;
7863 else
7864 address = Rn;
7865
7866 // R[t] = SignExtend(MemU[address,1], 32);
7867 RegisterInfo base_reg;
7868 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7869 RegisterInfo offset_reg;
7870 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
7871
7872 EmulateInstruction::Context context;
7873 context.type = eContextRegisterLoad;
7874 context.SetRegisterPlusIndirectOffset(base_reg, offset_reg);
7875
7876 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);
7877 if (!success)
7878 return false;
7879
7880 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7881 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7882 (uint64_t)signed_data))
7883 return false;
7884
7885 // if wback then R[n] = offset_addr;
7886 if (wback) {
7887 context.type = eContextAdjustBaseRegister;
7888 context.SetAddress(offset_addr);
7889 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7890 offset_addr))
7891 return false;
7892 }
7893 }
7894 return true;
7895 }
7896
7897 // LDRSH (immediate) calculates an address from a base register value and an
7898 // immediate offset, loads a halfword from
7899 // memory, sign-extends it to form a 32-bit word, and writes it to a register.
7900 // It can use offset, post-indexed, or pre-indexed addressing.
EmulateLDRSHImmediate(const uint32_t opcode,const ARMEncoding encoding)7901 bool EmulateInstructionARM::EmulateLDRSHImmediate(const uint32_t opcode,
7902 const ARMEncoding encoding) {
7903 #if 0
7904 if ConditionPassed() then
7905 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7906 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7907 address = if index then offset_addr else R[n];
7908 data = MemU[address,2];
7909 if wback then R[n] = offset_addr;
7910 if UnalignedSupport() || address<0> = '0' then
7911 R[t] = SignExtend(data, 32);
7912 else // Can only apply before ARMv7
7913 R[t] = bits(32) UNKNOWN;
7914 #endif
7915
7916 bool success = false;
7917
7918 if (ConditionPassed(opcode)) {
7919 uint32_t t;
7920 uint32_t n;
7921 uint32_t imm32;
7922 bool index;
7923 bool add;
7924 bool wback;
7925
7926 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7927 switch (encoding) {
7928 case eEncodingT1:
7929 // if Rn == '1111' then SEE LDRSH (literal);
7930 // if Rt == '1111' then SEE "Unallocated memory hints";
7931 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7932 t = Bits32(opcode, 15, 12);
7933 n = Bits32(opcode, 19, 16);
7934 imm32 = Bits32(opcode, 11, 0);
7935
7936 // index = TRUE; add = TRUE; wback = FALSE;
7937 index = true;
7938 add = true;
7939 wback = false;
7940
7941 // if t == 13 then UNPREDICTABLE;
7942 if (t == 13)
7943 return false;
7944
7945 break;
7946
7947 case eEncodingT2:
7948 // if Rn == '1111' then SEE LDRSH (literal);
7949 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE
7950 // "Unallocated memory hints";
7951 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7952 // if P == '0' && W == '0' then UNDEFINED;
7953 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
7954 return false;
7955
7956 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7957 t = Bits32(opcode, 15, 12);
7958 n = Bits32(opcode, 19, 16);
7959 imm32 = Bits32(opcode, 7, 0);
7960
7961 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7962 index = BitIsSet(opcode, 10);
7963 add = BitIsSet(opcode, 9);
7964 wback = BitIsSet(opcode, 8);
7965
7966 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7967 if (BadReg(t) || (wback && (n == t)))
7968 return false;
7969
7970 break;
7971
7972 case eEncodingA1: {
7973 // if Rn == '1111' then SEE LDRSH (literal);
7974 // if P == '0' && W == '1' then SEE LDRSHT;
7975 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7976 t = Bits32(opcode, 15, 12);
7977 n = Bits32(opcode, 19, 16);
7978 uint32_t imm4H = Bits32(opcode, 11, 8);
7979 uint32_t imm4L = Bits32(opcode, 3, 0);
7980 imm32 = (imm4H << 4) | imm4L;
7981
7982 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7983 // (W == '1');
7984 index = BitIsSet(opcode, 24);
7985 add = BitIsSet(opcode, 23);
7986 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
7987
7988 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7989 if ((t == 15) || (wback && (n == t)))
7990 return false;
7991
7992 break;
7993 }
7994
7995 default:
7996 return false;
7997 }
7998
7999 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
8000 uint64_t Rn =
8001 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8002 if (!success)
8003 return false;
8004
8005 addr_t offset_addr;
8006 if (add)
8007 offset_addr = Rn + imm32;
8008 else
8009 offset_addr = Rn - imm32;
8010
8011 // address = if index then offset_addr else R[n];
8012 addr_t address;
8013 if (index)
8014 address = offset_addr;
8015 else
8016 address = Rn;
8017
8018 // data = MemU[address,2];
8019 RegisterInfo base_reg;
8020 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
8021
8022 EmulateInstruction::Context context;
8023 context.type = eContextRegisterLoad;
8024 context.SetRegisterPlusOffset(base_reg, address - Rn);
8025
8026 uint64_t data = MemURead(context, address, 2, 0, &success);
8027 if (!success)
8028 return false;
8029
8030 // if wback then R[n] = offset_addr;
8031 if (wback) {
8032 context.type = eContextAdjustBaseRegister;
8033 context.SetAddress(offset_addr);
8034 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8035 offset_addr))
8036 return false;
8037 }
8038
8039 // if UnalignedSupport() || address<0> = '0' then
8040 if (UnalignedSupport() || BitIsClear(address, 0)) {
8041 // R[t] = SignExtend(data, 32);
8042 int64_t signed_data = llvm::SignExtend64<16>(data);
8043 context.type = eContextRegisterLoad;
8044 context.SetRegisterPlusOffset(base_reg, address - Rn);
8045 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
8046 (uint64_t)signed_data))
8047 return false;
8048 } else // Can only apply before ARMv7
8049 {
8050 // R[t] = bits(32) UNKNOWN;
8051 WriteBits32Unknown(t);
8052 }
8053 }
8054 return true;
8055 }
8056
8057 // LDRSH (literal) calculates an address from the PC value and an immediate
8058 // offset, loads a halfword from memory,
8059 // sign-extends it to from a 32-bit word, and writes it to a register.
EmulateLDRSHLiteral(const uint32_t opcode,const ARMEncoding encoding)8060 bool EmulateInstructionARM::EmulateLDRSHLiteral(const uint32_t opcode,
8061 const ARMEncoding encoding) {
8062 #if 0
8063 if ConditionPassed() then
8064 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
8065 base = Align(PC,4);
8066 address = if add then (base + imm32) else (base - imm32);
8067 data = MemU[address,2];
8068 if UnalignedSupport() || address<0> = '0' then
8069 R[t] = SignExtend(data, 32);
8070 else // Can only apply before ARMv7
8071 R[t] = bits(32) UNKNOWN;
8072 #endif
8073
8074 bool success = false;
8075
8076 if (ConditionPassed(opcode)) {
8077 uint32_t t;
8078 uint32_t imm32;
8079 bool add;
8080
8081 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
8082 switch (encoding) {
8083 case eEncodingT1:
8084 // if Rt == '1111' then SEE "Unallocated memory hints";
8085 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
8086 t = Bits32(opcode, 15, 12);
8087 imm32 = Bits32(opcode, 11, 0);
8088 add = BitIsSet(opcode, 23);
8089
8090 // if t == 13 then UNPREDICTABLE;
8091 if (t == 13)
8092 return false;
8093
8094 break;
8095
8096 case eEncodingA1: {
8097 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
8098 t = Bits32(opcode, 15, 12);
8099 uint32_t imm4H = Bits32(opcode, 11, 8);
8100 uint32_t imm4L = Bits32(opcode, 3, 0);
8101 imm32 = (imm4H << 4) | imm4L;
8102 add = BitIsSet(opcode, 23);
8103
8104 // if t == 15 then UNPREDICTABLE;
8105 if (t == 15)
8106 return false;
8107
8108 break;
8109 }
8110 default:
8111 return false;
8112 }
8113
8114 // base = Align(PC,4);
8115 uint64_t pc_value = ReadCoreReg(PC_REG, &success);
8116 if (!success)
8117 return false;
8118
8119 uint64_t base = AlignPC(pc_value);
8120
8121 addr_t address;
8122 // address = if add then (base + imm32) else (base - imm32);
8123 if (add)
8124 address = base + imm32;
8125 else
8126 address = base - imm32;
8127
8128 // data = MemU[address,2];
8129 RegisterInfo base_reg;
8130 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
8131
8132 EmulateInstruction::Context context;
8133 context.type = eContextRegisterLoad;
8134 context.SetRegisterPlusOffset(base_reg, imm32);
8135
8136 uint64_t data = MemURead(context, address, 2, 0, &success);
8137 if (!success)
8138 return false;
8139
8140 // if UnalignedSupport() || address<0> = '0' then
8141 if (UnalignedSupport() || BitIsClear(address, 0)) {
8142 // R[t] = SignExtend(data, 32);
8143 int64_t signed_data = llvm::SignExtend64<16>(data);
8144 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
8145 (uint64_t)signed_data))
8146 return false;
8147 } else // Can only apply before ARMv7
8148 {
8149 // R[t] = bits(32) UNKNOWN;
8150 WriteBits32Unknown(t);
8151 }
8152 }
8153 return true;
8154 }
8155
8156 // LDRSH (register) calculates an address from a base register value and an
8157 // offset register value, loads a halfword
8158 // from memory, sign-extends it to form a 32-bit word, and writes it to a
8159 // register. The offset register value can be shifted left by 0, 1, 2, or 3
8160 // bits.
EmulateLDRSHRegister(const uint32_t opcode,const ARMEncoding encoding)8161 bool EmulateInstructionARM::EmulateLDRSHRegister(const uint32_t opcode,
8162 const ARMEncoding encoding) {
8163 #if 0
8164 if ConditionPassed() then
8165 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
8166 offset = Shift(R[m], shift_t, shift_n, APSR.C);
8167 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
8168 address = if index then offset_addr else R[n];
8169 data = MemU[address,2];
8170 if wback then R[n] = offset_addr;
8171 if UnalignedSupport() || address<0> = '0' then
8172 R[t] = SignExtend(data, 32);
8173 else // Can only apply before ARMv7
8174 R[t] = bits(32) UNKNOWN;
8175 #endif
8176
8177 bool success = false;
8178
8179 if (ConditionPassed(opcode)) {
8180 uint32_t t;
8181 uint32_t n;
8182 uint32_t m;
8183 bool index;
8184 bool add;
8185 bool wback;
8186 ARM_ShifterType shift_t;
8187 uint32_t shift_n;
8188
8189 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
8190 switch (encoding) {
8191 case eEncodingT1:
8192 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
8193 // in ThumbEE";
8194 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8195 t = Bits32(opcode, 2, 0);
8196 n = Bits32(opcode, 5, 3);
8197 m = Bits32(opcode, 8, 6);
8198
8199 // index = TRUE; add = TRUE; wback = FALSE;
8200 index = true;
8201 add = true;
8202 wback = false;
8203
8204 // (shift_t, shift_n) = (SRType_LSL, 0);
8205 shift_t = SRType_LSL;
8206 shift_n = 0;
8207
8208 break;
8209
8210 case eEncodingT2:
8211 // if Rn == '1111' then SEE LDRSH (literal);
8212 // if Rt == '1111' then SEE "Unallocated memory hints";
8213 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8214 t = Bits32(opcode, 15, 12);
8215 n = Bits32(opcode, 19, 16);
8216 m = Bits32(opcode, 3, 0);
8217
8218 // index = TRUE; add = TRUE; wback = FALSE;
8219 index = true;
8220 add = true;
8221 wback = false;
8222
8223 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
8224 shift_t = SRType_LSL;
8225 shift_n = Bits32(opcode, 5, 4);
8226
8227 // if t == 13 || BadReg(m) then UNPREDICTABLE;
8228 if ((t == 13) || BadReg(m))
8229 return false;
8230
8231 break;
8232
8233 case eEncodingA1:
8234 // if P == '0' && W == '1' then SEE LDRSHT;
8235 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8236 t = Bits32(opcode, 15, 12);
8237 n = Bits32(opcode, 19, 16);
8238 m = Bits32(opcode, 3, 0);
8239
8240 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
8241 // (W == '1');
8242 index = BitIsSet(opcode, 24);
8243 add = BitIsSet(opcode, 23);
8244 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
8245
8246 // (shift_t, shift_n) = (SRType_LSL, 0);
8247 shift_t = SRType_LSL;
8248 shift_n = 0;
8249
8250 // if t == 15 || m == 15 then UNPREDICTABLE;
8251 if ((t == 15) || (m == 15))
8252 return false;
8253
8254 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
8255 if (wback && ((n == 15) || (n == t)))
8256 return false;
8257
8258 break;
8259
8260 default:
8261 return false;
8262 }
8263
8264 uint64_t Rm =
8265 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8266 if (!success)
8267 return false;
8268
8269 uint64_t Rn =
8270 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8271 if (!success)
8272 return false;
8273
8274 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
8275 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
8276 if (!success)
8277 return false;
8278
8279 addr_t offset_addr;
8280 addr_t address;
8281
8282 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
8283 if (add)
8284 offset_addr = Rn + offset;
8285 else
8286 offset_addr = Rn - offset;
8287
8288 // address = if index then offset_addr else R[n];
8289 if (index)
8290 address = offset_addr;
8291 else
8292 address = Rn;
8293
8294 // data = MemU[address,2];
8295 RegisterInfo base_reg;
8296 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
8297
8298 RegisterInfo offset_reg;
8299 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
8300
8301 EmulateInstruction::Context context;
8302 context.type = eContextRegisterLoad;
8303 context.SetRegisterPlusIndirectOffset(base_reg, offset_reg);
8304
8305 uint64_t data = MemURead(context, address, 2, 0, &success);
8306 if (!success)
8307 return false;
8308
8309 // if wback then R[n] = offset_addr;
8310 if (wback) {
8311 context.type = eContextAdjustBaseRegister;
8312 context.SetAddress(offset_addr);
8313 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8314 offset_addr))
8315 return false;
8316 }
8317
8318 // if UnalignedSupport() || address<0> = '0' then
8319 if (UnalignedSupport() || BitIsClear(address, 0)) {
8320 // R[t] = SignExtend(data, 32);
8321 context.type = eContextRegisterLoad;
8322 context.SetRegisterPlusIndirectOffset(base_reg, offset_reg);
8323
8324 int64_t signed_data = llvm::SignExtend64<16>(data);
8325 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
8326 (uint64_t)signed_data))
8327 return false;
8328 } else // Can only apply before ARMv7
8329 {
8330 // R[t] = bits(32) UNKNOWN;
8331 WriteBits32Unknown(t);
8332 }
8333 }
8334 return true;
8335 }
8336
8337 // SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and
8338 // writes the result to the destination
8339 // register. You can specifiy a rotation by 0, 8, 16, or 24 bits before
8340 // extracting the 8-bit value.
EmulateSXTB(const uint32_t opcode,const ARMEncoding encoding)8341 bool EmulateInstructionARM::EmulateSXTB(const uint32_t opcode,
8342 const ARMEncoding encoding) {
8343 #if 0
8344 if ConditionPassed() then
8345 EncodingSpecificOperations();
8346 rotated = ROR(R[m], rotation);
8347 R[d] = SignExtend(rotated<7:0>, 32);
8348 #endif
8349
8350 bool success = false;
8351
8352 if (ConditionPassed(opcode)) {
8353 uint32_t d;
8354 uint32_t m;
8355 uint32_t rotation;
8356
8357 // EncodingSpecificOperations();
8358 switch (encoding) {
8359 case eEncodingT1:
8360 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8361 d = Bits32(opcode, 2, 0);
8362 m = Bits32(opcode, 5, 3);
8363 rotation = 0;
8364
8365 break;
8366
8367 case eEncodingT2:
8368 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8369 d = Bits32(opcode, 11, 8);
8370 m = Bits32(opcode, 3, 0);
8371 rotation = Bits32(opcode, 5, 4) << 3;
8372
8373 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8374 if (BadReg(d) || BadReg(m))
8375 return false;
8376
8377 break;
8378
8379 case eEncodingA1:
8380 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8381 d = Bits32(opcode, 15, 12);
8382 m = Bits32(opcode, 3, 0);
8383 rotation = Bits32(opcode, 11, 10) << 3;
8384
8385 // if d == 15 || m == 15 then UNPREDICTABLE;
8386 if ((d == 15) || (m == 15))
8387 return false;
8388
8389 break;
8390
8391 default:
8392 return false;
8393 }
8394
8395 uint64_t Rm =
8396 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8397 if (!success)
8398 return false;
8399
8400 // rotated = ROR(R[m], rotation);
8401 uint64_t rotated = ROR(Rm, rotation, &success);
8402 if (!success)
8403 return false;
8404
8405 // R[d] = SignExtend(rotated<7:0>, 32);
8406 int64_t data = llvm::SignExtend64<8>(rotated);
8407
8408 RegisterInfo source_reg;
8409 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg);
8410
8411 EmulateInstruction::Context context;
8412 context.type = eContextRegisterLoad;
8413 context.SetRegister(source_reg);
8414
8415 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8416 (uint64_t)data))
8417 return false;
8418 }
8419 return true;
8420 }
8421
8422 // SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and
8423 // writes the result to the destination
8424 // register. You can specify a rotation by 0, 8, 16, or 24 bits before
8425 // extracting the 16-bit value.
EmulateSXTH(const uint32_t opcode,const ARMEncoding encoding)8426 bool EmulateInstructionARM::EmulateSXTH(const uint32_t opcode,
8427 const ARMEncoding encoding) {
8428 #if 0
8429 if ConditionPassed() then
8430 EncodingSpecificOperations();
8431 rotated = ROR(R[m], rotation);
8432 R[d] = SignExtend(rotated<15:0>, 32);
8433 #endif
8434
8435 bool success = false;
8436
8437 if (ConditionPassed(opcode)) {
8438 uint32_t d;
8439 uint32_t m;
8440 uint32_t rotation;
8441
8442 // EncodingSpecificOperations();
8443 switch (encoding) {
8444 case eEncodingT1:
8445 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8446 d = Bits32(opcode, 2, 0);
8447 m = Bits32(opcode, 5, 3);
8448 rotation = 0;
8449
8450 break;
8451
8452 case eEncodingT2:
8453 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8454 d = Bits32(opcode, 11, 8);
8455 m = Bits32(opcode, 3, 0);
8456 rotation = Bits32(opcode, 5, 4) << 3;
8457
8458 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8459 if (BadReg(d) || BadReg(m))
8460 return false;
8461
8462 break;
8463
8464 case eEncodingA1:
8465 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8466 d = Bits32(opcode, 15, 12);
8467 m = Bits32(opcode, 3, 0);
8468 rotation = Bits32(opcode, 11, 10) << 3;
8469
8470 // if d == 15 || m == 15 then UNPREDICTABLE;
8471 if ((d == 15) || (m == 15))
8472 return false;
8473
8474 break;
8475
8476 default:
8477 return false;
8478 }
8479
8480 uint64_t Rm =
8481 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8482 if (!success)
8483 return false;
8484
8485 // rotated = ROR(R[m], rotation);
8486 uint64_t rotated = ROR(Rm, rotation, &success);
8487 if (!success)
8488 return false;
8489
8490 // R[d] = SignExtend(rotated<15:0>, 32);
8491 RegisterInfo source_reg;
8492 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg);
8493
8494 EmulateInstruction::Context context;
8495 context.type = eContextRegisterLoad;
8496 context.SetRegister(source_reg);
8497
8498 int64_t data = llvm::SignExtend64<16>(rotated);
8499 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8500 (uint64_t)data))
8501 return false;
8502 }
8503
8504 return true;
8505 }
8506
8507 // UXTB extracts an 8-bit value from a register, zero-extends it to 32 bits, and
8508 // writes the result to the destination
8509 // register. You can specify a rotation by 0, 8, 16, or 24 bits before
8510 // extracting the 8-bit value.
EmulateUXTB(const uint32_t opcode,const ARMEncoding encoding)8511 bool EmulateInstructionARM::EmulateUXTB(const uint32_t opcode,
8512 const ARMEncoding encoding) {
8513 #if 0
8514 if ConditionPassed() then
8515 EncodingSpecificOperations();
8516 rotated = ROR(R[m], rotation);
8517 R[d] = ZeroExtend(rotated<7:0>, 32);
8518 #endif
8519
8520 bool success = false;
8521
8522 if (ConditionPassed(opcode)) {
8523 uint32_t d;
8524 uint32_t m;
8525 uint32_t rotation;
8526
8527 // EncodingSpecificOperations();
8528 switch (encoding) {
8529 case eEncodingT1:
8530 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8531 d = Bits32(opcode, 2, 0);
8532 m = Bits32(opcode, 5, 3);
8533 rotation = 0;
8534
8535 break;
8536
8537 case eEncodingT2:
8538 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8539 d = Bits32(opcode, 11, 8);
8540 m = Bits32(opcode, 3, 0);
8541 rotation = Bits32(opcode, 5, 4) << 3;
8542
8543 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8544 if (BadReg(d) || BadReg(m))
8545 return false;
8546
8547 break;
8548
8549 case eEncodingA1:
8550 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8551 d = Bits32(opcode, 15, 12);
8552 m = Bits32(opcode, 3, 0);
8553 rotation = Bits32(opcode, 11, 10) << 3;
8554
8555 // if d == 15 || m == 15 then UNPREDICTABLE;
8556 if ((d == 15) || (m == 15))
8557 return false;
8558
8559 break;
8560
8561 default:
8562 return false;
8563 }
8564
8565 uint64_t Rm =
8566 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8567 if (!success)
8568 return false;
8569
8570 // rotated = ROR(R[m], rotation);
8571 uint64_t rotated = ROR(Rm, rotation, &success);
8572 if (!success)
8573 return false;
8574
8575 // R[d] = ZeroExtend(rotated<7:0>, 32);
8576 RegisterInfo source_reg;
8577 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg);
8578
8579 EmulateInstruction::Context context;
8580 context.type = eContextRegisterLoad;
8581 context.SetRegister(source_reg);
8582
8583 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8584 Bits32(rotated, 7, 0)))
8585 return false;
8586 }
8587 return true;
8588 }
8589
8590 // UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and
8591 // writes the result to the destination
8592 // register. You can specify a rotation by 0, 8, 16, or 24 bits before
8593 // extracting the 16-bit value.
EmulateUXTH(const uint32_t opcode,const ARMEncoding encoding)8594 bool EmulateInstructionARM::EmulateUXTH(const uint32_t opcode,
8595 const ARMEncoding encoding) {
8596 #if 0
8597 if ConditionPassed() then
8598 EncodingSpecificOperations();
8599 rotated = ROR(R[m], rotation);
8600 R[d] = ZeroExtend(rotated<15:0>, 32);
8601 #endif
8602
8603 bool success = false;
8604
8605 if (ConditionPassed(opcode)) {
8606 uint32_t d;
8607 uint32_t m;
8608 uint32_t rotation;
8609
8610 switch (encoding) {
8611 case eEncodingT1:
8612 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8613 d = Bits32(opcode, 2, 0);
8614 m = Bits32(opcode, 5, 3);
8615 rotation = 0;
8616
8617 break;
8618
8619 case eEncodingT2:
8620 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8621 d = Bits32(opcode, 11, 8);
8622 m = Bits32(opcode, 3, 0);
8623 rotation = Bits32(opcode, 5, 4) << 3;
8624
8625 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8626 if (BadReg(d) || BadReg(m))
8627 return false;
8628
8629 break;
8630
8631 case eEncodingA1:
8632 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8633 d = Bits32(opcode, 15, 12);
8634 m = Bits32(opcode, 3, 0);
8635 rotation = Bits32(opcode, 11, 10) << 3;
8636
8637 // if d == 15 || m == 15 then UNPREDICTABLE;
8638 if ((d == 15) || (m == 15))
8639 return false;
8640
8641 break;
8642
8643 default:
8644 return false;
8645 }
8646
8647 uint64_t Rm =
8648 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8649 if (!success)
8650 return false;
8651
8652 // rotated = ROR(R[m], rotation);
8653 uint64_t rotated = ROR(Rm, rotation, &success);
8654 if (!success)
8655 return false;
8656
8657 // R[d] = ZeroExtend(rotated<15:0>, 32);
8658 RegisterInfo source_reg;
8659 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg);
8660
8661 EmulateInstruction::Context context;
8662 context.type = eContextRegisterLoad;
8663 context.SetRegister(source_reg);
8664
8665 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8666 Bits32(rotated, 15, 0)))
8667 return false;
8668 }
8669 return true;
8670 }
8671
8672 // RFE (Return From Exception) loads the PC and the CPSR from the word at the
8673 // specified address and the following
8674 // word respectively.
EmulateRFE(const uint32_t opcode,const ARMEncoding encoding)8675 bool EmulateInstructionARM::EmulateRFE(const uint32_t opcode,
8676 const ARMEncoding encoding) {
8677 #if 0
8678 if ConditionPassed() then
8679 EncodingSpecificOperations();
8680 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8681 UNPREDICTABLE;
8682 else
8683 address = if increment then R[n] else R[n]-8;
8684 if wordhigher then address = address+4;
8685 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
8686 BranchWritePC(MemA[address,4]);
8687 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8688 #endif
8689
8690 bool success = false;
8691
8692 if (ConditionPassed(opcode)) {
8693 uint32_t n;
8694 bool wback;
8695 bool increment;
8696 bool wordhigher;
8697
8698 // EncodingSpecificOperations();
8699 switch (encoding) {
8700 case eEncodingT1:
8701 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher =
8702 // FALSE;
8703 n = Bits32(opcode, 19, 16);
8704 wback = BitIsSet(opcode, 21);
8705 increment = false;
8706 wordhigher = false;
8707
8708 // if n == 15 then UNPREDICTABLE;
8709 if (n == 15)
8710 return false;
8711
8712 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8713 if (InITBlock() && !LastInITBlock())
8714 return false;
8715
8716 break;
8717
8718 case eEncodingT2:
8719 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
8720 n = Bits32(opcode, 19, 16);
8721 wback = BitIsSet(opcode, 21);
8722 increment = true;
8723 wordhigher = false;
8724
8725 // if n == 15 then UNPREDICTABLE;
8726 if (n == 15)
8727 return false;
8728
8729 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8730 if (InITBlock() && !LastInITBlock())
8731 return false;
8732
8733 break;
8734
8735 case eEncodingA1:
8736 // n = UInt(Rn);
8737 n = Bits32(opcode, 19, 16);
8738
8739 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
8740 wback = BitIsSet(opcode, 21);
8741 increment = BitIsSet(opcode, 23);
8742 wordhigher = (Bit32(opcode, 24) == Bit32(opcode, 23));
8743
8744 // if n == 15 then UNPREDICTABLE;
8745 if (n == 15)
8746 return false;
8747
8748 break;
8749
8750 default:
8751 return false;
8752 }
8753
8754 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE
8755 // then
8756 if (!CurrentModeIsPrivileged())
8757 // UNPREDICTABLE;
8758 return false;
8759 else {
8760 uint64_t Rn =
8761 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8762 if (!success)
8763 return false;
8764
8765 addr_t address;
8766 // address = if increment then R[n] else R[n]-8;
8767 if (increment)
8768 address = Rn;
8769 else
8770 address = Rn - 8;
8771
8772 // if wordhigher then address = address+4;
8773 if (wordhigher)
8774 address = address + 4;
8775
8776 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
8777 RegisterInfo base_reg;
8778 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
8779
8780 EmulateInstruction::Context context;
8781 context.type = eContextReturnFromException;
8782 context.SetRegisterPlusOffset(base_reg, address - Rn);
8783
8784 uint64_t data = MemARead(context, address + 4, 4, 0, &success);
8785 if (!success)
8786 return false;
8787
8788 CPSRWriteByInstr(data, 15, true);
8789
8790 // BranchWritePC(MemA[address,4]);
8791 uint64_t data2 = MemARead(context, address, 4, 0, &success);
8792 if (!success)
8793 return false;
8794
8795 BranchWritePC(context, data2);
8796
8797 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8798 if (wback) {
8799 context.type = eContextAdjustBaseRegister;
8800 if (increment) {
8801 context.SetOffset(8);
8802 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8803 Rn + 8))
8804 return false;
8805 } else {
8806 context.SetOffset(-8);
8807 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8808 Rn - 8))
8809 return false;
8810 }
8811 } // if wback
8812 }
8813 } // if ConditionPassed()
8814 return true;
8815 }
8816
8817 // Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a
8818 // register value and an immediate value, and writes the result to the
8819 // destination register. It can optionally update the condition flags based on
8820 // the result.
EmulateEORImm(const uint32_t opcode,const ARMEncoding encoding)8821 bool EmulateInstructionARM::EmulateEORImm(const uint32_t opcode,
8822 const ARMEncoding encoding) {
8823 #if 0
8824 // ARM pseudo code...
8825 if ConditionPassed() then
8826 EncodingSpecificOperations();
8827 result = R[n] EOR imm32;
8828 if d == 15 then // Can only occur for ARM encoding
8829 ALUWritePC(result); // setflags is always FALSE here
8830 else
8831 R[d] = result;
8832 if setflags then
8833 APSR.N = result<31>;
8834 APSR.Z = IsZeroBit(result);
8835 APSR.C = carry;
8836 // APSR.V unchanged
8837 #endif
8838
8839 bool success = false;
8840
8841 if (ConditionPassed(opcode)) {
8842 uint32_t Rd, Rn;
8843 uint32_t
8844 imm32; // the immediate value to be ORed to the value obtained from Rn
8845 bool setflags;
8846 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8847 switch (encoding) {
8848 case eEncodingT1:
8849 Rd = Bits32(opcode, 11, 8);
8850 Rn = Bits32(opcode, 19, 16);
8851 setflags = BitIsSet(opcode, 20);
8852 imm32 = ThumbExpandImm_C(
8853 opcode, APSR_C,
8854 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8855 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8856 if (Rd == 15 && setflags)
8857 return EmulateTEQImm(opcode, eEncodingT1);
8858 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8859 return false;
8860 break;
8861 case eEncodingA1:
8862 Rd = Bits32(opcode, 15, 12);
8863 Rn = Bits32(opcode, 19, 16);
8864 setflags = BitIsSet(opcode, 20);
8865 imm32 =
8866 ARMExpandImm_C(opcode, APSR_C,
8867 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8868
8869 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
8870 // instructions;
8871 if (Rd == 15 && setflags)
8872 return EmulateSUBSPcLrEtc(opcode, encoding);
8873 break;
8874 default:
8875 return false;
8876 }
8877
8878 // Read the first operand.
8879 uint32_t val1 = ReadCoreReg(Rn, &success);
8880 if (!success)
8881 return false;
8882
8883 uint32_t result = val1 ^ imm32;
8884
8885 EmulateInstruction::Context context;
8886 context.type = EmulateInstruction::eContextImmediate;
8887 context.SetNoArgs();
8888
8889 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8890 return false;
8891 }
8892 return true;
8893 }
8894
8895 // Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a
8896 // register value and an optionally-shifted register value, and writes the
8897 // result to the destination register. It can optionally update the condition
8898 // flags based on the result.
EmulateEORReg(const uint32_t opcode,const ARMEncoding encoding)8899 bool EmulateInstructionARM::EmulateEORReg(const uint32_t opcode,
8900 const ARMEncoding encoding) {
8901 #if 0
8902 // ARM pseudo code...
8903 if ConditionPassed() then
8904 EncodingSpecificOperations();
8905 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8906 result = R[n] EOR shifted;
8907 if d == 15 then // Can only occur for ARM encoding
8908 ALUWritePC(result); // setflags is always FALSE here
8909 else
8910 R[d] = result;
8911 if setflags then
8912 APSR.N = result<31>;
8913 APSR.Z = IsZeroBit(result);
8914 APSR.C = carry;
8915 // APSR.V unchanged
8916 #endif
8917
8918 bool success = false;
8919
8920 if (ConditionPassed(opcode)) {
8921 uint32_t Rd, Rn, Rm;
8922 ARM_ShifterType shift_t;
8923 uint32_t shift_n; // the shift applied to the value read from Rm
8924 bool setflags;
8925 uint32_t carry;
8926 switch (encoding) {
8927 case eEncodingT1:
8928 Rd = Rn = Bits32(opcode, 2, 0);
8929 Rm = Bits32(opcode, 5, 3);
8930 setflags = !InITBlock();
8931 shift_t = SRType_LSL;
8932 shift_n = 0;
8933 break;
8934 case eEncodingT2:
8935 Rd = Bits32(opcode, 11, 8);
8936 Rn = Bits32(opcode, 19, 16);
8937 Rm = Bits32(opcode, 3, 0);
8938 setflags = BitIsSet(opcode, 20);
8939 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8940 // if Rd == '1111' && S == '1' then SEE TEQ (register);
8941 if (Rd == 15 && setflags)
8942 return EmulateTEQReg(opcode, eEncodingT1);
8943 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8944 return false;
8945 break;
8946 case eEncodingA1:
8947 Rd = Bits32(opcode, 15, 12);
8948 Rn = Bits32(opcode, 19, 16);
8949 Rm = Bits32(opcode, 3, 0);
8950 setflags = BitIsSet(opcode, 20);
8951 shift_n = DecodeImmShiftARM(opcode, shift_t);
8952
8953 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
8954 // instructions;
8955 if (Rd == 15 && setflags)
8956 return EmulateSUBSPcLrEtc(opcode, encoding);
8957 break;
8958 default:
8959 return false;
8960 }
8961
8962 // Read the first operand.
8963 uint32_t val1 = ReadCoreReg(Rn, &success);
8964 if (!success)
8965 return false;
8966
8967 // Read the second operand.
8968 uint32_t val2 = ReadCoreReg(Rm, &success);
8969 if (!success)
8970 return false;
8971
8972 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
8973 if (!success)
8974 return false;
8975 uint32_t result = val1 ^ shifted;
8976
8977 EmulateInstruction::Context context;
8978 context.type = EmulateInstruction::eContextImmediate;
8979 context.SetNoArgs();
8980
8981 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8982 return false;
8983 }
8984 return true;
8985 }
8986
8987 // Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value
8988 // and an immediate value, and writes the result to the destination register.
8989 // It can optionally update the condition flags based on the result.
EmulateORRImm(const uint32_t opcode,const ARMEncoding encoding)8990 bool EmulateInstructionARM::EmulateORRImm(const uint32_t opcode,
8991 const ARMEncoding encoding) {
8992 #if 0
8993 // ARM pseudo code...
8994 if ConditionPassed() then
8995 EncodingSpecificOperations();
8996 result = R[n] OR imm32;
8997 if d == 15 then // Can only occur for ARM encoding
8998 ALUWritePC(result); // setflags is always FALSE here
8999 else
9000 R[d] = result;
9001 if setflags then
9002 APSR.N = result<31>;
9003 APSR.Z = IsZeroBit(result);
9004 APSR.C = carry;
9005 // APSR.V unchanged
9006 #endif
9007
9008 bool success = false;
9009
9010 if (ConditionPassed(opcode)) {
9011 uint32_t Rd, Rn;
9012 uint32_t
9013 imm32; // the immediate value to be ORed to the value obtained from Rn
9014 bool setflags;
9015 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9016 switch (encoding) {
9017 case eEncodingT1:
9018 Rd = Bits32(opcode, 11, 8);
9019 Rn = Bits32(opcode, 19, 16);
9020 setflags = BitIsSet(opcode, 20);
9021 imm32 = ThumbExpandImm_C(
9022 opcode, APSR_C,
9023 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9024 // if Rn == '1111' then SEE MOV (immediate);
9025 if (Rn == 15)
9026 return EmulateMOVRdImm(opcode, eEncodingT2);
9027 if (BadReg(Rd) || Rn == 13)
9028 return false;
9029 break;
9030 case eEncodingA1:
9031 Rd = Bits32(opcode, 15, 12);
9032 Rn = Bits32(opcode, 19, 16);
9033 setflags = BitIsSet(opcode, 20);
9034 imm32 =
9035 ARMExpandImm_C(opcode, APSR_C,
9036 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9037
9038 if (Rd == 15 && setflags)
9039 return EmulateSUBSPcLrEtc(opcode, encoding);
9040 break;
9041 default:
9042 return false;
9043 }
9044
9045 // Read the first operand.
9046 uint32_t val1 = ReadCoreReg(Rn, &success);
9047 if (!success)
9048 return false;
9049
9050 uint32_t result = val1 | imm32;
9051
9052 EmulateInstruction::Context context;
9053 context.type = EmulateInstruction::eContextImmediate;
9054 context.SetNoArgs();
9055
9056 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
9057 return false;
9058 }
9059 return true;
9060 }
9061
9062 // Bitwise OR (register) performs a bitwise (inclusive) OR of a register value
9063 // and an optionally-shifted register value, and writes the result to the
9064 // destination register. It can optionally update the condition flags based on
9065 // the result.
EmulateORRReg(const uint32_t opcode,const ARMEncoding encoding)9066 bool EmulateInstructionARM::EmulateORRReg(const uint32_t opcode,
9067 const ARMEncoding encoding) {
9068 #if 0
9069 // ARM pseudo code...
9070 if ConditionPassed() then
9071 EncodingSpecificOperations();
9072 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9073 result = R[n] OR shifted;
9074 if d == 15 then // Can only occur for ARM encoding
9075 ALUWritePC(result); // setflags is always FALSE here
9076 else
9077 R[d] = result;
9078 if setflags then
9079 APSR.N = result<31>;
9080 APSR.Z = IsZeroBit(result);
9081 APSR.C = carry;
9082 // APSR.V unchanged
9083 #endif
9084
9085 bool success = false;
9086
9087 if (ConditionPassed(opcode)) {
9088 uint32_t Rd, Rn, Rm;
9089 ARM_ShifterType shift_t;
9090 uint32_t shift_n; // the shift applied to the value read from Rm
9091 bool setflags;
9092 uint32_t carry;
9093 switch (encoding) {
9094 case eEncodingT1:
9095 Rd = Rn = Bits32(opcode, 2, 0);
9096 Rm = Bits32(opcode, 5, 3);
9097 setflags = !InITBlock();
9098 shift_t = SRType_LSL;
9099 shift_n = 0;
9100 break;
9101 case eEncodingT2:
9102 Rd = Bits32(opcode, 11, 8);
9103 Rn = Bits32(opcode, 19, 16);
9104 Rm = Bits32(opcode, 3, 0);
9105 setflags = BitIsSet(opcode, 20);
9106 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9107 // if Rn == '1111' then SEE MOV (register);
9108 if (Rn == 15)
9109 return EmulateMOVRdRm(opcode, eEncodingT3);
9110 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
9111 return false;
9112 break;
9113 case eEncodingA1:
9114 Rd = Bits32(opcode, 15, 12);
9115 Rn = Bits32(opcode, 19, 16);
9116 Rm = Bits32(opcode, 3, 0);
9117 setflags = BitIsSet(opcode, 20);
9118 shift_n = DecodeImmShiftARM(opcode, shift_t);
9119
9120 if (Rd == 15 && setflags)
9121 return EmulateSUBSPcLrEtc(opcode, encoding);
9122 break;
9123 default:
9124 return false;
9125 }
9126
9127 // Read the first operand.
9128 uint32_t val1 = ReadCoreReg(Rn, &success);
9129 if (!success)
9130 return false;
9131
9132 // Read the second operand.
9133 uint32_t val2 = ReadCoreReg(Rm, &success);
9134 if (!success)
9135 return false;
9136
9137 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9138 if (!success)
9139 return false;
9140 uint32_t result = val1 | shifted;
9141
9142 EmulateInstruction::Context context;
9143 context.type = EmulateInstruction::eContextImmediate;
9144 context.SetNoArgs();
9145
9146 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
9147 return false;
9148 }
9149 return true;
9150 }
9151
9152 // Reverse Subtract (immediate) subtracts a register value from an immediate
9153 // value, and writes the result to the destination register. It can optionally
9154 // update the condition flags based on the result.
EmulateRSBImm(const uint32_t opcode,const ARMEncoding encoding)9155 bool EmulateInstructionARM::EmulateRSBImm(const uint32_t opcode,
9156 const ARMEncoding encoding) {
9157 #if 0
9158 // ARM pseudo code...
9159 if ConditionPassed() then
9160 EncodingSpecificOperations();
9161 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
9162 if d == 15 then // Can only occur for ARM encoding
9163 ALUWritePC(result); // setflags is always FALSE here
9164 else
9165 R[d] = result;
9166 if setflags then
9167 APSR.N = result<31>;
9168 APSR.Z = IsZeroBit(result);
9169 APSR.C = carry;
9170 APSR.V = overflow;
9171 #endif
9172
9173 bool success = false;
9174
9175 uint32_t Rd; // the destination register
9176 uint32_t Rn; // the first operand
9177 bool setflags;
9178 uint32_t
9179 imm32; // the immediate value to be added to the value obtained from Rn
9180 switch (encoding) {
9181 case eEncodingT1:
9182 Rd = Bits32(opcode, 2, 0);
9183 Rn = Bits32(opcode, 5, 3);
9184 setflags = !InITBlock();
9185 imm32 = 0;
9186 break;
9187 case eEncodingT2:
9188 Rd = Bits32(opcode, 11, 8);
9189 Rn = Bits32(opcode, 19, 16);
9190 setflags = BitIsSet(opcode, 20);
9191 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9192 if (BadReg(Rd) || BadReg(Rn))
9193 return false;
9194 break;
9195 case eEncodingA1:
9196 Rd = Bits32(opcode, 15, 12);
9197 Rn = Bits32(opcode, 19, 16);
9198 setflags = BitIsSet(opcode, 20);
9199 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9200
9201 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9202 // instructions;
9203 if (Rd == 15 && setflags)
9204 return EmulateSUBSPcLrEtc(opcode, encoding);
9205 break;
9206 default:
9207 return false;
9208 }
9209 // Read the register value from the operand register Rn.
9210 uint32_t reg_val = ReadCoreReg(Rn, &success);
9211 if (!success)
9212 return false;
9213
9214 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
9215
9216 EmulateInstruction::Context context;
9217 context.type = EmulateInstruction::eContextImmediate;
9218 context.SetNoArgs();
9219
9220 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9221 res.carry_out, res.overflow);
9222 }
9223
9224 // Reverse Subtract (register) subtracts a register value from an optionally-
9225 // shifted register value, and writes the result to the destination register.
9226 // It can optionally update the condition flags based on the result.
EmulateRSBReg(const uint32_t opcode,const ARMEncoding encoding)9227 bool EmulateInstructionARM::EmulateRSBReg(const uint32_t opcode,
9228 const ARMEncoding encoding) {
9229 #if 0
9230 // ARM pseudo code...
9231 if ConditionPassed() then
9232 EncodingSpecificOperations();
9233 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9234 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
9235 if d == 15 then // Can only occur for ARM encoding
9236 ALUWritePC(result); // setflags is always FALSE here
9237 else
9238 R[d] = result;
9239 if setflags then
9240 APSR.N = result<31>;
9241 APSR.Z = IsZeroBit(result);
9242 APSR.C = carry;
9243 APSR.V = overflow;
9244 #endif
9245
9246 bool success = false;
9247
9248 uint32_t Rd; // the destination register
9249 uint32_t Rn; // the first operand
9250 uint32_t Rm; // the second operand
9251 bool setflags;
9252 ARM_ShifterType shift_t;
9253 uint32_t shift_n; // the shift applied to the value read from Rm
9254 switch (encoding) {
9255 case eEncodingT1:
9256 Rd = Bits32(opcode, 11, 8);
9257 Rn = Bits32(opcode, 19, 16);
9258 Rm = Bits32(opcode, 3, 0);
9259 setflags = BitIsSet(opcode, 20);
9260 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9261 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
9262 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
9263 return false;
9264 break;
9265 case eEncodingA1:
9266 Rd = Bits32(opcode, 15, 12);
9267 Rn = Bits32(opcode, 19, 16);
9268 Rm = Bits32(opcode, 3, 0);
9269 setflags = BitIsSet(opcode, 20);
9270 shift_n = DecodeImmShiftARM(opcode, shift_t);
9271
9272 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9273 // instructions;
9274 if (Rd == 15 && setflags)
9275 return EmulateSUBSPcLrEtc(opcode, encoding);
9276 break;
9277 default:
9278 return false;
9279 }
9280 // Read the register value from register Rn.
9281 uint32_t val1 = ReadCoreReg(Rn, &success);
9282 if (!success)
9283 return false;
9284
9285 // Read the register value from register Rm.
9286 uint32_t val2 = ReadCoreReg(Rm, &success);
9287 if (!success)
9288 return false;
9289
9290 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
9291 if (!success)
9292 return false;
9293 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
9294
9295 EmulateInstruction::Context context;
9296 context.type = EmulateInstruction::eContextImmediate;
9297 context.SetNoArgs();
9298 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9299 res.carry_out, res.overflow);
9300 }
9301
9302 // Reverse Subtract with Carry (immediate) subtracts a register value and the
9303 // value of NOT (Carry flag) from an immediate value, and writes the result to
9304 // the destination register. It can optionally update the condition flags based
9305 // on the result.
EmulateRSCImm(const uint32_t opcode,const ARMEncoding encoding)9306 bool EmulateInstructionARM::EmulateRSCImm(const uint32_t opcode,
9307 const ARMEncoding encoding) {
9308 #if 0
9309 // ARM pseudo code...
9310 if ConditionPassed() then
9311 EncodingSpecificOperations();
9312 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
9313 if d == 15 then
9314 ALUWritePC(result); // setflags is always FALSE here
9315 else
9316 R[d] = result;
9317 if setflags then
9318 APSR.N = result<31>;
9319 APSR.Z = IsZeroBit(result);
9320 APSR.C = carry;
9321 APSR.V = overflow;
9322 #endif
9323
9324 bool success = false;
9325
9326 uint32_t Rd; // the destination register
9327 uint32_t Rn; // the first operand
9328 bool setflags;
9329 uint32_t
9330 imm32; // the immediate value to be added to the value obtained from Rn
9331 switch (encoding) {
9332 case eEncodingA1:
9333 Rd = Bits32(opcode, 15, 12);
9334 Rn = Bits32(opcode, 19, 16);
9335 setflags = BitIsSet(opcode, 20);
9336 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9337
9338 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9339 // instructions;
9340 if (Rd == 15 && setflags)
9341 return EmulateSUBSPcLrEtc(opcode, encoding);
9342 break;
9343 default:
9344 return false;
9345 }
9346 // Read the register value from the operand register Rn.
9347 uint32_t reg_val = ReadCoreReg(Rn, &success);
9348 if (!success)
9349 return false;
9350
9351 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
9352
9353 EmulateInstruction::Context context;
9354 context.type = EmulateInstruction::eContextImmediate;
9355 context.SetNoArgs();
9356
9357 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9358 res.carry_out, res.overflow);
9359 }
9360
9361 // Reverse Subtract with Carry (register) subtracts a register value and the
9362 // value of NOT (Carry flag) from an optionally-shifted register value, and
9363 // writes the result to the destination register. It can optionally update the
9364 // condition flags based on the result.
EmulateRSCReg(const uint32_t opcode,const ARMEncoding encoding)9365 bool EmulateInstructionARM::EmulateRSCReg(const uint32_t opcode,
9366 const ARMEncoding encoding) {
9367 #if 0
9368 // ARM pseudo code...
9369 if ConditionPassed() then
9370 EncodingSpecificOperations();
9371 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9372 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
9373 if d == 15 then
9374 ALUWritePC(result); // setflags is always FALSE here
9375 else
9376 R[d] = result;
9377 if setflags then
9378 APSR.N = result<31>;
9379 APSR.Z = IsZeroBit(result);
9380 APSR.C = carry;
9381 APSR.V = overflow;
9382 #endif
9383
9384 bool success = false;
9385
9386 uint32_t Rd; // the destination register
9387 uint32_t Rn; // the first operand
9388 uint32_t Rm; // the second operand
9389 bool setflags;
9390 ARM_ShifterType shift_t;
9391 uint32_t shift_n; // the shift applied to the value read from Rm
9392 switch (encoding) {
9393 case eEncodingA1:
9394 Rd = Bits32(opcode, 15, 12);
9395 Rn = Bits32(opcode, 19, 16);
9396 Rm = Bits32(opcode, 3, 0);
9397 setflags = BitIsSet(opcode, 20);
9398 shift_n = DecodeImmShiftARM(opcode, shift_t);
9399
9400 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9401 // instructions;
9402 if (Rd == 15 && setflags)
9403 return EmulateSUBSPcLrEtc(opcode, encoding);
9404 break;
9405 default:
9406 return false;
9407 }
9408 // Read the register value from register Rn.
9409 uint32_t val1 = ReadCoreReg(Rn, &success);
9410 if (!success)
9411 return false;
9412
9413 // Read the register value from register Rm.
9414 uint32_t val2 = ReadCoreReg(Rm, &success);
9415 if (!success)
9416 return false;
9417
9418 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
9419 if (!success)
9420 return false;
9421 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
9422
9423 EmulateInstruction::Context context;
9424 context.type = EmulateInstruction::eContextImmediate;
9425 context.SetNoArgs();
9426 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9427 res.carry_out, res.overflow);
9428 }
9429
9430 // Subtract with Carry (immediate) subtracts an immediate value and the value
9431 // of
9432 // NOT (Carry flag) from a register value, and writes the result to the
9433 // destination register.
9434 // It can optionally update the condition flags based on the result.
EmulateSBCImm(const uint32_t opcode,const ARMEncoding encoding)9435 bool EmulateInstructionARM::EmulateSBCImm(const uint32_t opcode,
9436 const ARMEncoding encoding) {
9437 #if 0
9438 // ARM pseudo code...
9439 if ConditionPassed() then
9440 EncodingSpecificOperations();
9441 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
9442 if d == 15 then // Can only occur for ARM encoding
9443 ALUWritePC(result); // setflags is always FALSE here
9444 else
9445 R[d] = result;
9446 if setflags then
9447 APSR.N = result<31>;
9448 APSR.Z = IsZeroBit(result);
9449 APSR.C = carry;
9450 APSR.V = overflow;
9451 #endif
9452
9453 bool success = false;
9454
9455 uint32_t Rd; // the destination register
9456 uint32_t Rn; // the first operand
9457 bool setflags;
9458 uint32_t
9459 imm32; // the immediate value to be added to the value obtained from Rn
9460 switch (encoding) {
9461 case eEncodingT1:
9462 Rd = Bits32(opcode, 11, 8);
9463 Rn = Bits32(opcode, 19, 16);
9464 setflags = BitIsSet(opcode, 20);
9465 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9466 if (BadReg(Rd) || BadReg(Rn))
9467 return false;
9468 break;
9469 case eEncodingA1:
9470 Rd = Bits32(opcode, 15, 12);
9471 Rn = Bits32(opcode, 19, 16);
9472 setflags = BitIsSet(opcode, 20);
9473 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9474
9475 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9476 // instructions;
9477 if (Rd == 15 && setflags)
9478 return EmulateSUBSPcLrEtc(opcode, encoding);
9479 break;
9480 default:
9481 return false;
9482 }
9483 // Read the register value from the operand register Rn.
9484 uint32_t reg_val = ReadCoreReg(Rn, &success);
9485 if (!success)
9486 return false;
9487
9488 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
9489
9490 EmulateInstruction::Context context;
9491 context.type = EmulateInstruction::eContextImmediate;
9492 context.SetNoArgs();
9493
9494 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9495 res.carry_out, res.overflow);
9496 }
9497
9498 // Subtract with Carry (register) subtracts an optionally-shifted register
9499 // value and the value of
9500 // NOT (Carry flag) from a register value, and writes the result to the
9501 // destination register.
9502 // It can optionally update the condition flags based on the result.
EmulateSBCReg(const uint32_t opcode,const ARMEncoding encoding)9503 bool EmulateInstructionARM::EmulateSBCReg(const uint32_t opcode,
9504 const ARMEncoding encoding) {
9505 #if 0
9506 // ARM pseudo code...
9507 if ConditionPassed() then
9508 EncodingSpecificOperations();
9509 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9510 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
9511 if d == 15 then // Can only occur for ARM encoding
9512 ALUWritePC(result); // setflags is always FALSE here
9513 else
9514 R[d] = result;
9515 if setflags then
9516 APSR.N = result<31>;
9517 APSR.Z = IsZeroBit(result);
9518 APSR.C = carry;
9519 APSR.V = overflow;
9520 #endif
9521
9522 bool success = false;
9523
9524 uint32_t Rd; // the destination register
9525 uint32_t Rn; // the first operand
9526 uint32_t Rm; // the second operand
9527 bool setflags;
9528 ARM_ShifterType shift_t;
9529 uint32_t shift_n; // the shift applied to the value read from Rm
9530 switch (encoding) {
9531 case eEncodingT1:
9532 Rd = Rn = Bits32(opcode, 2, 0);
9533 Rm = Bits32(opcode, 5, 3);
9534 setflags = !InITBlock();
9535 shift_t = SRType_LSL;
9536 shift_n = 0;
9537 break;
9538 case eEncodingT2:
9539 Rd = Bits32(opcode, 11, 8);
9540 Rn = Bits32(opcode, 19, 16);
9541 Rm = Bits32(opcode, 3, 0);
9542 setflags = BitIsSet(opcode, 20);
9543 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9544 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
9545 return false;
9546 break;
9547 case eEncodingA1:
9548 Rd = Bits32(opcode, 15, 12);
9549 Rn = Bits32(opcode, 19, 16);
9550 Rm = Bits32(opcode, 3, 0);
9551 setflags = BitIsSet(opcode, 20);
9552 shift_n = DecodeImmShiftARM(opcode, shift_t);
9553
9554 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9555 // instructions;
9556 if (Rd == 15 && setflags)
9557 return EmulateSUBSPcLrEtc(opcode, encoding);
9558 break;
9559 default:
9560 return false;
9561 }
9562 // Read the register value from register Rn.
9563 uint32_t val1 = ReadCoreReg(Rn, &success);
9564 if (!success)
9565 return false;
9566
9567 // Read the register value from register Rm.
9568 uint32_t val2 = ReadCoreReg(Rm, &success);
9569 if (!success)
9570 return false;
9571
9572 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
9573 if (!success)
9574 return false;
9575 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
9576
9577 EmulateInstruction::Context context;
9578 context.type = EmulateInstruction::eContextImmediate;
9579 context.SetNoArgs();
9580 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9581 res.carry_out, res.overflow);
9582 }
9583
9584 // This instruction subtracts an immediate value from a register value, and
9585 // writes the result to the destination register. It can optionally update the
9586 // condition flags based on the result.
EmulateSUBImmThumb(const uint32_t opcode,const ARMEncoding encoding)9587 bool EmulateInstructionARM::EmulateSUBImmThumb(const uint32_t opcode,
9588 const ARMEncoding encoding) {
9589 #if 0
9590 // ARM pseudo code...
9591 if ConditionPassed() then
9592 EncodingSpecificOperations();
9593 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9594 R[d] = result;
9595 if setflags then
9596 APSR.N = result<31>;
9597 APSR.Z = IsZeroBit(result);
9598 APSR.C = carry;
9599 APSR.V = overflow;
9600 #endif
9601
9602 bool success = false;
9603
9604 uint32_t Rd; // the destination register
9605 uint32_t Rn; // the first operand
9606 bool setflags;
9607 uint32_t imm32; // the immediate value to be subtracted from the value
9608 // obtained from Rn
9609 switch (encoding) {
9610 case eEncodingT1:
9611 Rd = Bits32(opcode, 2, 0);
9612 Rn = Bits32(opcode, 5, 3);
9613 setflags = !InITBlock();
9614 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
9615 break;
9616 case eEncodingT2:
9617 Rd = Rn = Bits32(opcode, 10, 8);
9618 setflags = !InITBlock();
9619 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
9620 break;
9621 case eEncodingT3:
9622 Rd = Bits32(opcode, 11, 8);
9623 Rn = Bits32(opcode, 19, 16);
9624 setflags = BitIsSet(opcode, 20);
9625 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9626
9627 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
9628 if (Rd == 15 && setflags)
9629 return EmulateCMPImm(opcode, eEncodingT2);
9630
9631 // if Rn == '1101' then SEE SUB (SP minus immediate);
9632 if (Rn == 13)
9633 return EmulateSUBSPImm(opcode, eEncodingT2);
9634
9635 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
9636 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
9637 return false;
9638 break;
9639 case eEncodingT4:
9640 Rd = Bits32(opcode, 11, 8);
9641 Rn = Bits32(opcode, 19, 16);
9642 setflags = BitIsSet(opcode, 20);
9643 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
9644
9645 // if Rn == '1111' then SEE ADR;
9646 if (Rn == 15)
9647 return EmulateADR(opcode, eEncodingT2);
9648
9649 // if Rn == '1101' then SEE SUB (SP minus immediate);
9650 if (Rn == 13)
9651 return EmulateSUBSPImm(opcode, eEncodingT3);
9652
9653 if (BadReg(Rd))
9654 return false;
9655 break;
9656 default:
9657 return false;
9658 }
9659 // Read the register value from the operand register Rn.
9660 uint32_t reg_val = ReadCoreReg(Rn, &success);
9661 if (!success)
9662 return false;
9663
9664 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9665
9666 EmulateInstruction::Context context;
9667 context.type = EmulateInstruction::eContextImmediate;
9668 context.SetNoArgs();
9669
9670 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9671 res.carry_out, res.overflow);
9672 }
9673
9674 // This instruction subtracts an immediate value from a register value, and
9675 // writes the result to the destination register. It can optionally update the
9676 // condition flags based on the result.
EmulateSUBImmARM(const uint32_t opcode,const ARMEncoding encoding)9677 bool EmulateInstructionARM::EmulateSUBImmARM(const uint32_t opcode,
9678 const ARMEncoding encoding) {
9679 #if 0
9680 // ARM pseudo code...
9681 if ConditionPassed() then
9682 EncodingSpecificOperations();
9683 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9684 if d == 15 then
9685 ALUWritePC(result); // setflags is always FALSE here
9686 else
9687 R[d] = result;
9688 if setflags then
9689 APSR.N = result<31>;
9690 APSR.Z = IsZeroBit(result);
9691 APSR.C = carry;
9692 APSR.V = overflow;
9693 #endif
9694
9695 bool success = false;
9696
9697 if (ConditionPassed(opcode)) {
9698 uint32_t Rd; // the destination register
9699 uint32_t Rn; // the first operand
9700 bool setflags;
9701 uint32_t imm32; // the immediate value to be subtracted from the value
9702 // obtained from Rn
9703 switch (encoding) {
9704 case eEncodingA1:
9705 Rd = Bits32(opcode, 15, 12);
9706 Rn = Bits32(opcode, 19, 16);
9707 setflags = BitIsSet(opcode, 20);
9708 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9709
9710 // if Rn == '1111' && S == '0' then SEE ADR;
9711 if (Rn == 15 && !setflags)
9712 return EmulateADR(opcode, eEncodingA2);
9713
9714 // if Rn == '1101' then SEE SUB (SP minus immediate);
9715 if (Rn == 13)
9716 return EmulateSUBSPImm(opcode, eEncodingA1);
9717
9718 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9719 // instructions;
9720 if (Rd == 15 && setflags)
9721 return EmulateSUBSPcLrEtc(opcode, encoding);
9722 break;
9723 default:
9724 return false;
9725 }
9726 // Read the register value from the operand register Rn.
9727 uint32_t reg_val = ReadCoreReg(Rn, &success);
9728 if (!success)
9729 return false;
9730
9731 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9732
9733 EmulateInstruction::Context context;
9734 if (Rd == 13)
9735 context.type = EmulateInstruction::eContextAdjustStackPointer;
9736 else
9737 context.type = EmulateInstruction::eContextRegisterPlusOffset;
9738
9739 RegisterInfo dwarf_reg;
9740 GetRegisterInfo(eRegisterKindDWARF, Rn, dwarf_reg);
9741 int64_t imm32_signed = imm32;
9742 context.SetRegisterPlusOffset(dwarf_reg, -imm32_signed);
9743
9744 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9745 res.carry_out, res.overflow))
9746 return false;
9747 }
9748 return true;
9749 }
9750
9751 // Test Equivalence (immediate) performs a bitwise exclusive OR operation on a
9752 // register value and an immediate value. It updates the condition flags based
9753 // on the result, and discards the result.
EmulateTEQImm(const uint32_t opcode,const ARMEncoding encoding)9754 bool EmulateInstructionARM::EmulateTEQImm(const uint32_t opcode,
9755 const ARMEncoding encoding) {
9756 #if 0
9757 // ARM pseudo code...
9758 if ConditionPassed() then
9759 EncodingSpecificOperations();
9760 result = R[n] EOR imm32;
9761 APSR.N = result<31>;
9762 APSR.Z = IsZeroBit(result);
9763 APSR.C = carry;
9764 // APSR.V unchanged
9765 #endif
9766
9767 bool success = false;
9768
9769 if (ConditionPassed(opcode)) {
9770 uint32_t Rn;
9771 uint32_t
9772 imm32; // the immediate value to be ANDed to the value obtained from Rn
9773 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9774 switch (encoding) {
9775 case eEncodingT1:
9776 Rn = Bits32(opcode, 19, 16);
9777 imm32 = ThumbExpandImm_C(
9778 opcode, APSR_C,
9779 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9780 if (BadReg(Rn))
9781 return false;
9782 break;
9783 case eEncodingA1:
9784 Rn = Bits32(opcode, 19, 16);
9785 imm32 =
9786 ARMExpandImm_C(opcode, APSR_C,
9787 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9788 break;
9789 default:
9790 return false;
9791 }
9792
9793 // Read the first operand.
9794 uint32_t val1 = ReadCoreReg(Rn, &success);
9795 if (!success)
9796 return false;
9797
9798 uint32_t result = val1 ^ imm32;
9799
9800 EmulateInstruction::Context context;
9801 context.type = EmulateInstruction::eContextImmediate;
9802 context.SetNoArgs();
9803
9804 if (!WriteFlags(context, result, carry))
9805 return false;
9806 }
9807 return true;
9808 }
9809
9810 // Test Equivalence (register) performs a bitwise exclusive OR operation on a
9811 // register value and an optionally-shifted register value. It updates the
9812 // condition flags based on the result, and discards the result.
EmulateTEQReg(const uint32_t opcode,const ARMEncoding encoding)9813 bool EmulateInstructionARM::EmulateTEQReg(const uint32_t opcode,
9814 const ARMEncoding encoding) {
9815 #if 0
9816 // ARM pseudo code...
9817 if ConditionPassed() then
9818 EncodingSpecificOperations();
9819 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9820 result = R[n] EOR shifted;
9821 APSR.N = result<31>;
9822 APSR.Z = IsZeroBit(result);
9823 APSR.C = carry;
9824 // APSR.V unchanged
9825 #endif
9826
9827 bool success = false;
9828
9829 if (ConditionPassed(opcode)) {
9830 uint32_t Rn, Rm;
9831 ARM_ShifterType shift_t;
9832 uint32_t shift_n; // the shift applied to the value read from Rm
9833 uint32_t carry;
9834 switch (encoding) {
9835 case eEncodingT1:
9836 Rn = Bits32(opcode, 19, 16);
9837 Rm = Bits32(opcode, 3, 0);
9838 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9839 if (BadReg(Rn) || BadReg(Rm))
9840 return false;
9841 break;
9842 case eEncodingA1:
9843 Rn = Bits32(opcode, 19, 16);
9844 Rm = Bits32(opcode, 3, 0);
9845 shift_n = DecodeImmShiftARM(opcode, shift_t);
9846 break;
9847 default:
9848 return false;
9849 }
9850
9851 // Read the first operand.
9852 uint32_t val1 = ReadCoreReg(Rn, &success);
9853 if (!success)
9854 return false;
9855
9856 // Read the second operand.
9857 uint32_t val2 = ReadCoreReg(Rm, &success);
9858 if (!success)
9859 return false;
9860
9861 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9862 if (!success)
9863 return false;
9864 uint32_t result = val1 ^ shifted;
9865
9866 EmulateInstruction::Context context;
9867 context.type = EmulateInstruction::eContextImmediate;
9868 context.SetNoArgs();
9869
9870 if (!WriteFlags(context, result, carry))
9871 return false;
9872 }
9873 return true;
9874 }
9875
9876 // Test (immediate) performs a bitwise AND operation on a register value and an
9877 // immediate value. It updates the condition flags based on the result, and
9878 // discards the result.
EmulateTSTImm(const uint32_t opcode,const ARMEncoding encoding)9879 bool EmulateInstructionARM::EmulateTSTImm(const uint32_t opcode,
9880 const ARMEncoding encoding) {
9881 #if 0
9882 // ARM pseudo code...
9883 if ConditionPassed() then
9884 EncodingSpecificOperations();
9885 result = R[n] AND imm32;
9886 APSR.N = result<31>;
9887 APSR.Z = IsZeroBit(result);
9888 APSR.C = carry;
9889 // APSR.V unchanged
9890 #endif
9891
9892 bool success = false;
9893
9894 if (ConditionPassed(opcode)) {
9895 uint32_t Rn;
9896 uint32_t
9897 imm32; // the immediate value to be ANDed to the value obtained from Rn
9898 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9899 switch (encoding) {
9900 case eEncodingT1:
9901 Rn = Bits32(opcode, 19, 16);
9902 imm32 = ThumbExpandImm_C(
9903 opcode, APSR_C,
9904 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9905 if (BadReg(Rn))
9906 return false;
9907 break;
9908 case eEncodingA1:
9909 Rn = Bits32(opcode, 19, 16);
9910 imm32 =
9911 ARMExpandImm_C(opcode, APSR_C,
9912 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9913 break;
9914 default:
9915 return false;
9916 }
9917
9918 // Read the first operand.
9919 uint32_t val1 = ReadCoreReg(Rn, &success);
9920 if (!success)
9921 return false;
9922
9923 uint32_t result = val1 & imm32;
9924
9925 EmulateInstruction::Context context;
9926 context.type = EmulateInstruction::eContextImmediate;
9927 context.SetNoArgs();
9928
9929 if (!WriteFlags(context, result, carry))
9930 return false;
9931 }
9932 return true;
9933 }
9934
9935 // Test (register) performs a bitwise AND operation on a register value and an
9936 // optionally-shifted register value. It updates the condition flags based on
9937 // the result, and discards the result.
EmulateTSTReg(const uint32_t opcode,const ARMEncoding encoding)9938 bool EmulateInstructionARM::EmulateTSTReg(const uint32_t opcode,
9939 const ARMEncoding encoding) {
9940 #if 0
9941 // ARM pseudo code...
9942 if ConditionPassed() then
9943 EncodingSpecificOperations();
9944 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9945 result = R[n] AND shifted;
9946 APSR.N = result<31>;
9947 APSR.Z = IsZeroBit(result);
9948 APSR.C = carry;
9949 // APSR.V unchanged
9950 #endif
9951
9952 bool success = false;
9953
9954 if (ConditionPassed(opcode)) {
9955 uint32_t Rn, Rm;
9956 ARM_ShifterType shift_t;
9957 uint32_t shift_n; // the shift applied to the value read from Rm
9958 uint32_t carry;
9959 switch (encoding) {
9960 case eEncodingT1:
9961 Rn = Bits32(opcode, 2, 0);
9962 Rm = Bits32(opcode, 5, 3);
9963 shift_t = SRType_LSL;
9964 shift_n = 0;
9965 break;
9966 case eEncodingT2:
9967 Rn = Bits32(opcode, 19, 16);
9968 Rm = Bits32(opcode, 3, 0);
9969 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9970 if (BadReg(Rn) || BadReg(Rm))
9971 return false;
9972 break;
9973 case eEncodingA1:
9974 Rn = Bits32(opcode, 19, 16);
9975 Rm = Bits32(opcode, 3, 0);
9976 shift_n = DecodeImmShiftARM(opcode, shift_t);
9977 break;
9978 default:
9979 return false;
9980 }
9981
9982 // Read the first operand.
9983 uint32_t val1 = ReadCoreReg(Rn, &success);
9984 if (!success)
9985 return false;
9986
9987 // Read the second operand.
9988 uint32_t val2 = ReadCoreReg(Rm, &success);
9989 if (!success)
9990 return false;
9991
9992 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9993 if (!success)
9994 return false;
9995 uint32_t result = val1 & shifted;
9996
9997 EmulateInstruction::Context context;
9998 context.type = EmulateInstruction::eContextImmediate;
9999 context.SetNoArgs();
10000
10001 if (!WriteFlags(context, result, carry))
10002 return false;
10003 }
10004 return true;
10005 }
10006
10007 // A8.6.216 SUB (SP minus register)
EmulateSUBSPReg(const uint32_t opcode,const ARMEncoding encoding)10008 bool EmulateInstructionARM::EmulateSUBSPReg(const uint32_t opcode,
10009 const ARMEncoding encoding) {
10010 #if 0
10011 if ConditionPassed() then
10012 EncodingSpecificOperations();
10013 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10014 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');
10015 if d == 15 then // Can only occur for ARM encoding
10016 ALUWritePC(result); // setflags is always FALSE here
10017 else
10018 R[d] = result;
10019 if setflags then
10020 APSR.N = result<31>;
10021 APSR.Z = IsZeroBit(result);
10022 APSR.C = carry;
10023 APSR.V = overflow;
10024 #endif
10025
10026 bool success = false;
10027
10028 if (ConditionPassed(opcode)) {
10029 uint32_t d;
10030 uint32_t m;
10031 bool setflags;
10032 ARM_ShifterType shift_t;
10033 uint32_t shift_n;
10034
10035 switch (encoding) {
10036 case eEncodingT1:
10037 // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
10038 d = Bits32(opcode, 11, 8);
10039 m = Bits32(opcode, 3, 0);
10040 setflags = BitIsSet(opcode, 20);
10041
10042 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
10043 shift_n = DecodeImmShiftThumb(opcode, shift_t);
10044
10045 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then
10046 // UNPREDICTABLE;
10047 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
10048 return false;
10049
10050 // if d == 15 || BadReg(m) then UNPREDICTABLE;
10051 if ((d == 15) || BadReg(m))
10052 return false;
10053 break;
10054
10055 case eEncodingA1:
10056 // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
10057 d = Bits32(opcode, 15, 12);
10058 m = Bits32(opcode, 3, 0);
10059 setflags = BitIsSet(opcode, 20);
10060
10061 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
10062 // instructions;
10063 if (d == 15 && setflags)
10064 EmulateSUBSPcLrEtc(opcode, encoding);
10065
10066 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
10067 shift_n = DecodeImmShiftARM(opcode, shift_t);
10068 break;
10069
10070 default:
10071 return false;
10072 }
10073
10074 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10075 uint32_t Rm = ReadCoreReg(m, &success);
10076 if (!success)
10077 return false;
10078
10079 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);
10080 if (!success)
10081 return false;
10082
10083 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');
10084 uint32_t sp_val = ReadCoreReg(SP_REG, &success);
10085 if (!success)
10086 return false;
10087
10088 AddWithCarryResult res = AddWithCarry(sp_val, ~shifted, 1);
10089
10090 EmulateInstruction::Context context;
10091 context.type = eContextArithmetic;
10092 RegisterInfo sp_reg;
10093 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg);
10094 RegisterInfo dwarf_reg;
10095 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, dwarf_reg);
10096 context.SetRegisterRegisterOperands(sp_reg, dwarf_reg);
10097
10098 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags,
10099 res.carry_out, res.overflow))
10100 return false;
10101 }
10102 return true;
10103 }
10104
10105 // A8.6.7 ADD (register-shifted register)
EmulateADDRegShift(const uint32_t opcode,const ARMEncoding encoding)10106 bool EmulateInstructionARM::EmulateADDRegShift(const uint32_t opcode,
10107 const ARMEncoding encoding) {
10108 #if 0
10109 if ConditionPassed() then
10110 EncodingSpecificOperations();
10111 shift_n = UInt(R[s]<7:0>);
10112 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10113 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
10114 R[d] = result;
10115 if setflags then
10116 APSR.N = result<31>;
10117 APSR.Z = IsZeroBit(result);
10118 APSR.C = carry;
10119 APSR.V = overflow;
10120 #endif
10121
10122 bool success = false;
10123
10124 if (ConditionPassed(opcode)) {
10125 uint32_t d;
10126 uint32_t n;
10127 uint32_t m;
10128 uint32_t s;
10129 bool setflags;
10130 ARM_ShifterType shift_t;
10131
10132 switch (encoding) {
10133 case eEncodingA1:
10134 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
10135 d = Bits32(opcode, 15, 12);
10136 n = Bits32(opcode, 19, 16);
10137 m = Bits32(opcode, 3, 0);
10138 s = Bits32(opcode, 11, 8);
10139
10140 // setflags = (S == '1'); shift_t = DecodeRegShift(type);
10141 setflags = BitIsSet(opcode, 20);
10142 shift_t = DecodeRegShift(Bits32(opcode, 6, 5));
10143
10144 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
10145 if ((d == 15) || (n == 15) || (m == 15) || (s == 15))
10146 return false;
10147 break;
10148
10149 default:
10150 return false;
10151 }
10152
10153 // shift_n = UInt(R[s]<7:0>);
10154 uint32_t Rs = ReadCoreReg(s, &success);
10155 if (!success)
10156 return false;
10157
10158 uint32_t shift_n = Bits32(Rs, 7, 0);
10159
10160 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10161 uint32_t Rm = ReadCoreReg(m, &success);
10162 if (!success)
10163 return false;
10164
10165 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);
10166 if (!success)
10167 return false;
10168
10169 // (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
10170 uint32_t Rn = ReadCoreReg(n, &success);
10171 if (!success)
10172 return false;
10173
10174 AddWithCarryResult res = AddWithCarry(Rn, shifted, 0);
10175
10176 // R[d] = result;
10177 EmulateInstruction::Context context;
10178 context.type = eContextArithmetic;
10179 RegisterInfo reg_n;
10180 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, reg_n);
10181 RegisterInfo reg_m;
10182 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, reg_m);
10183
10184 context.SetRegisterRegisterOperands(reg_n, reg_m);
10185
10186 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
10187 res.result))
10188 return false;
10189
10190 // if setflags then
10191 // APSR.N = result<31>;
10192 // APSR.Z = IsZeroBit(result);
10193 // APSR.C = carry;
10194 // APSR.V = overflow;
10195 if (setflags)
10196 return WriteFlags(context, res.result, res.carry_out, res.overflow);
10197 }
10198 return true;
10199 }
10200
10201 // A8.6.213 SUB (register)
EmulateSUBReg(const uint32_t opcode,const ARMEncoding encoding)10202 bool EmulateInstructionARM::EmulateSUBReg(const uint32_t opcode,
10203 const ARMEncoding encoding) {
10204 #if 0
10205 if ConditionPassed() then
10206 EncodingSpecificOperations();
10207 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10208 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
10209 if d == 15 then // Can only occur for ARM encoding
10210 ALUWritePC(result); // setflags is always FALSE here
10211 else
10212 R[d] = result;
10213 if setflags then
10214 APSR.N = result<31>;
10215 APSR.Z = IsZeroBit(result);
10216 APSR.C = carry;
10217 APSR.V = overflow;
10218 #endif
10219
10220 bool success = false;
10221
10222 if (ConditionPassed(opcode)) {
10223 uint32_t d;
10224 uint32_t n;
10225 uint32_t m;
10226 bool setflags;
10227 ARM_ShifterType shift_t;
10228 uint32_t shift_n;
10229
10230 switch (encoding) {
10231 case eEncodingT1:
10232 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
10233 d = Bits32(opcode, 2, 0);
10234 n = Bits32(opcode, 5, 3);
10235 m = Bits32(opcode, 8, 6);
10236 setflags = !InITBlock();
10237
10238 // (shift_t, shift_n) = (SRType_LSL, 0);
10239 shift_t = SRType_LSL;
10240 shift_n = 0;
10241
10242 break;
10243
10244 case eEncodingT2:
10245 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S =="1");
10246 d = Bits32(opcode, 11, 8);
10247 n = Bits32(opcode, 19, 16);
10248 m = Bits32(opcode, 3, 0);
10249 setflags = BitIsSet(opcode, 20);
10250
10251 // if Rd == "1111" && S == "1" then SEE CMP (register);
10252 if (d == 15 && setflags == 1)
10253 return EmulateCMPImm(opcode, eEncodingT3);
10254
10255 // if Rn == "1101" then SEE SUB (SP minus register);
10256 if (n == 13)
10257 return EmulateSUBSPReg(opcode, eEncodingT1);
10258
10259 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
10260 shift_n = DecodeImmShiftThumb(opcode, shift_t);
10261
10262 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then
10263 // UNPREDICTABLE;
10264 if ((d == 13) || ((d == 15) && BitIsClear(opcode, 20)) || (n == 15) ||
10265 BadReg(m))
10266 return false;
10267
10268 break;
10269
10270 case eEncodingA1:
10271 // if Rn == '1101' then SEE SUB (SP minus register);
10272 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
10273 d = Bits32(opcode, 15, 12);
10274 n = Bits32(opcode, 19, 16);
10275 m = Bits32(opcode, 3, 0);
10276 setflags = BitIsSet(opcode, 20);
10277
10278 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
10279 // instructions;
10280 if ((d == 15) && setflags)
10281 EmulateSUBSPcLrEtc(opcode, encoding);
10282
10283 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
10284 shift_n = DecodeImmShiftARM(opcode, shift_t);
10285
10286 break;
10287
10288 default:
10289 return false;
10290 }
10291
10292 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10293 uint32_t Rm = ReadCoreReg(m, &success);
10294 if (!success)
10295 return false;
10296
10297 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);
10298 if (!success)
10299 return false;
10300
10301 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
10302 uint32_t Rn = ReadCoreReg(n, &success);
10303 if (!success)
10304 return false;
10305
10306 AddWithCarryResult res = AddWithCarry(Rn, ~shifted, 1);
10307
10308 // if d == 15 then // Can only occur for ARM encoding ALUWritePC(result);
10309 // // setflags is always FALSE here else
10310 // R[d] = result;
10311 // if setflags then
10312 // APSR.N = result<31>;
10313 // APSR.Z = IsZeroBit(result);
10314 // APSR.C = carry;
10315 // APSR.V = overflow;
10316
10317 EmulateInstruction::Context context;
10318 context.type = eContextArithmetic;
10319 RegisterInfo reg_n;
10320 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, reg_n);
10321 RegisterInfo reg_m;
10322 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, reg_m);
10323 context.SetRegisterRegisterOperands(reg_n, reg_m);
10324
10325 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags,
10326 res.carry_out, res.overflow))
10327 return false;
10328 }
10329 return true;
10330 }
10331
10332 // A8.6.202 STREX
10333 // Store Register Exclusive calculates an address from a base register value
10334 // and an immediate offset, and stores a word from a register to memory if the
10335 // executing processor has exclusive access to the memory addressed.
EmulateSTREX(const uint32_t opcode,const ARMEncoding encoding)10336 bool EmulateInstructionARM::EmulateSTREX(const uint32_t opcode,
10337 const ARMEncoding encoding) {
10338 #if 0
10339 if ConditionPassed() then
10340 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10341 address = R[n] + imm32;
10342 if ExclusiveMonitorsPass(address,4) then
10343 MemA[address,4] = R[t];
10344 R[d] = 0;
10345 else
10346 R[d] = 1;
10347 #endif
10348
10349 bool success = false;
10350
10351 if (ConditionPassed(opcode)) {
10352 uint32_t d;
10353 uint32_t t;
10354 uint32_t n;
10355 uint32_t imm32;
10356 const uint32_t addr_byte_size = GetAddressByteSize();
10357
10358 switch (encoding) {
10359 case eEncodingT1:
10360 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 =
10361 // ZeroExtend(imm8:'00',
10362 // 32);
10363 d = Bits32(opcode, 11, 8);
10364 t = Bits32(opcode, 15, 12);
10365 n = Bits32(opcode, 19, 16);
10366 imm32 = Bits32(opcode, 7, 0) << 2;
10367
10368 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
10369 if (BadReg(d) || BadReg(t) || (n == 15))
10370 return false;
10371
10372 // if d == n || d == t then UNPREDICTABLE;
10373 if ((d == n) || (d == t))
10374 return false;
10375
10376 break;
10377
10378 case eEncodingA1:
10379 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero
10380 // offset
10381 d = Bits32(opcode, 15, 12);
10382 t = Bits32(opcode, 3, 0);
10383 n = Bits32(opcode, 19, 16);
10384 imm32 = 0;
10385
10386 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
10387 if ((d == 15) || (t == 15) || (n == 15))
10388 return false;
10389
10390 // if d == n || d == t then UNPREDICTABLE;
10391 if ((d == n) || (d == t))
10392 return false;
10393
10394 break;
10395
10396 default:
10397 return false;
10398 }
10399
10400 // address = R[n] + imm32;
10401 uint32_t Rn = ReadCoreReg(n, &success);
10402 if (!success)
10403 return false;
10404
10405 addr_t address = Rn + imm32;
10406
10407 RegisterInfo base_reg;
10408 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10409 RegisterInfo data_reg;
10410 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
10411 EmulateInstruction::Context context;
10412 context.type = eContextRegisterStore;
10413 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, imm32);
10414
10415 // if ExclusiveMonitorsPass(address,4) then if (ExclusiveMonitorsPass
10416 // (address, addr_byte_size)) -- For now, for the sake of emulation, we
10417 // will say this
10418 // always return
10419 // true.
10420 if (true) {
10421 // MemA[address,4] = R[t];
10422 uint32_t Rt =
10423 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
10424 if (!success)
10425 return false;
10426
10427 if (!MemAWrite(context, address, Rt, addr_byte_size))
10428 return false;
10429
10430 // R[d] = 0;
10431 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 0))
10432 return false;
10433 }
10434 #if 0 // unreachable because if true
10435 else
10436 {
10437 // R[d] = 1;
10438 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
10439 return false;
10440 }
10441 #endif // unreachable because if true
10442 }
10443 return true;
10444 }
10445
10446 // A8.6.197 STRB (immediate, ARM)
EmulateSTRBImmARM(const uint32_t opcode,const ARMEncoding encoding)10447 bool EmulateInstructionARM::EmulateSTRBImmARM(const uint32_t opcode,
10448 const ARMEncoding encoding) {
10449 #if 0
10450 if ConditionPassed() then
10451 EncodingSpecificOperations();
10452 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10453 address = if index then offset_addr else R[n];
10454 MemU[address,1] = R[t]<7:0>;
10455 if wback then R[n] = offset_addr;
10456 #endif
10457
10458 bool success = false;
10459
10460 if (ConditionPassed(opcode)) {
10461 uint32_t t;
10462 uint32_t n;
10463 uint32_t imm32;
10464 bool index;
10465 bool add;
10466 bool wback;
10467
10468 switch (encoding) {
10469 case eEncodingA1:
10470 // if P == '0' && W == '1' then SEE STRBT;
10471 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
10472 t = Bits32(opcode, 15, 12);
10473 n = Bits32(opcode, 19, 16);
10474 imm32 = Bits32(opcode, 11, 0);
10475
10476 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10477 index = BitIsSet(opcode, 24);
10478 add = BitIsSet(opcode, 23);
10479 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10480
10481 // if t == 15 then UNPREDICTABLE;
10482 if (t == 15)
10483 return false;
10484
10485 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
10486 if (wback && ((n == 15) || (n == t)))
10487 return false;
10488
10489 break;
10490
10491 default:
10492 return false;
10493 }
10494
10495 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10496 uint32_t Rn = ReadCoreReg(n, &success);
10497 if (!success)
10498 return false;
10499
10500 addr_t offset_addr;
10501 if (add)
10502 offset_addr = Rn + imm32;
10503 else
10504 offset_addr = Rn - imm32;
10505
10506 // address = if index then offset_addr else R[n];
10507 addr_t address;
10508 if (index)
10509 address = offset_addr;
10510 else
10511 address = Rn;
10512
10513 // MemU[address,1] = R[t]<7:0>;
10514 uint32_t Rt = ReadCoreReg(t, &success);
10515 if (!success)
10516 return false;
10517
10518 RegisterInfo base_reg;
10519 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10520 RegisterInfo data_reg;
10521 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
10522 EmulateInstruction::Context context;
10523 context.type = eContextRegisterStore;
10524 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
10525
10526 if (!MemUWrite(context, address, Bits32(Rt, 7, 0), 1))
10527 return false;
10528
10529 // if wback then R[n] = offset_addr;
10530 if (wback) {
10531 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10532 offset_addr))
10533 return false;
10534 }
10535 }
10536 return true;
10537 }
10538
10539 // A8.6.194 STR (immediate, ARM)
EmulateSTRImmARM(const uint32_t opcode,const ARMEncoding encoding)10540 bool EmulateInstructionARM::EmulateSTRImmARM(const uint32_t opcode,
10541 const ARMEncoding encoding) {
10542 #if 0
10543 if ConditionPassed() then
10544 EncodingSpecificOperations();
10545 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10546 address = if index then offset_addr else R[n];
10547 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
10548 if wback then R[n] = offset_addr;
10549 #endif
10550
10551 bool success = false;
10552
10553 if (ConditionPassed(opcode)) {
10554 uint32_t t;
10555 uint32_t n;
10556 uint32_t imm32;
10557 bool index;
10558 bool add;
10559 bool wback;
10560
10561 const uint32_t addr_byte_size = GetAddressByteSize();
10562
10563 switch (encoding) {
10564 case eEncodingA1:
10565 // if P == '0' && W == '1' then SEE STRT;
10566 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 ==
10567 // '000000000100' then SEE PUSH;
10568 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
10569 t = Bits32(opcode, 15, 12);
10570 n = Bits32(opcode, 19, 16);
10571 imm32 = Bits32(opcode, 11, 0);
10572
10573 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10574 index = BitIsSet(opcode, 24);
10575 add = BitIsSet(opcode, 23);
10576 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10577
10578 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
10579 if (wback && ((n == 15) || (n == t)))
10580 return false;
10581
10582 break;
10583
10584 default:
10585 return false;
10586 }
10587
10588 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10589 uint32_t Rn = ReadCoreReg(n, &success);
10590 if (!success)
10591 return false;
10592
10593 addr_t offset_addr;
10594 if (add)
10595 offset_addr = Rn + imm32;
10596 else
10597 offset_addr = Rn - imm32;
10598
10599 // address = if index then offset_addr else R[n];
10600 addr_t address;
10601 if (index)
10602 address = offset_addr;
10603 else
10604 address = Rn;
10605
10606 RegisterInfo base_reg;
10607 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10608 RegisterInfo data_reg;
10609 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
10610 EmulateInstruction::Context context;
10611 context.type = eContextRegisterStore;
10612 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
10613
10614 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
10615 uint32_t Rt = ReadCoreReg(t, &success);
10616 if (!success)
10617 return false;
10618
10619 if (t == 15) {
10620 uint32_t pc_value = ReadCoreReg(PC_REG, &success);
10621 if (!success)
10622 return false;
10623
10624 if (!MemUWrite(context, address, pc_value, addr_byte_size))
10625 return false;
10626 } else {
10627 if (!MemUWrite(context, address, Rt, addr_byte_size))
10628 return false;
10629 }
10630
10631 // if wback then R[n] = offset_addr;
10632 if (wback) {
10633 context.type = eContextAdjustBaseRegister;
10634 context.SetImmediate(offset_addr);
10635
10636 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10637 offset_addr))
10638 return false;
10639 }
10640 }
10641 return true;
10642 }
10643
10644 // A8.6.66 LDRD (immediate)
10645 // Load Register Dual (immediate) calculates an address from a base register
10646 // value and an immediate offset, loads two words from memory, and writes them
10647 // to two registers. It can use offset, post-indexed, or pre-indexed
10648 // addressing.
EmulateLDRDImmediate(const uint32_t opcode,const ARMEncoding encoding)10649 bool EmulateInstructionARM::EmulateLDRDImmediate(const uint32_t opcode,
10650 const ARMEncoding encoding) {
10651 #if 0
10652 if ConditionPassed() then
10653 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10654 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10655 address = if index then offset_addr else R[n];
10656 R[t] = MemA[address,4];
10657 R[t2] = MemA[address+4,4];
10658 if wback then R[n] = offset_addr;
10659 #endif
10660
10661 bool success = false;
10662
10663 if (ConditionPassed(opcode)) {
10664 uint32_t t;
10665 uint32_t t2;
10666 uint32_t n;
10667 uint32_t imm32;
10668 bool index;
10669 bool add;
10670 bool wback;
10671
10672 switch (encoding) {
10673 case eEncodingT1:
10674 // if P == '0' && W == '0' then SEE 'Related encodings';
10675 // if Rn == '1111' then SEE LDRD (literal);
10676 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 =
10677 // ZeroExtend(imm8:'00', 32);
10678 t = Bits32(opcode, 15, 12);
10679 t2 = Bits32(opcode, 11, 8);
10680 n = Bits32(opcode, 19, 16);
10681 imm32 = Bits32(opcode, 7, 0) << 2;
10682
10683 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
10684 index = BitIsSet(opcode, 24);
10685 add = BitIsSet(opcode, 23);
10686 wback = BitIsSet(opcode, 21);
10687
10688 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10689 if (wback && ((n == t) || (n == t2)))
10690 return false;
10691
10692 // if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
10693 if (BadReg(t) || BadReg(t2) || (t == t2))
10694 return false;
10695
10696 break;
10697
10698 case eEncodingA1:
10699 // if Rn == '1111' then SEE LDRD (literal);
10700 // if Rt<0> == '1' then UNPREDICTABLE;
10701 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L,
10702 // 32);
10703 t = Bits32(opcode, 15, 12);
10704 if (BitIsSet(t, 0))
10705 return false;
10706 t2 = t + 1;
10707 n = Bits32(opcode, 19, 16);
10708 imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0);
10709
10710 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10711 index = BitIsSet(opcode, 24);
10712 add = BitIsSet(opcode, 23);
10713 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10714
10715 // if P == '0' && W == '1' then UNPREDICTABLE;
10716 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
10717 return false;
10718
10719 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10720 if (wback && ((n == t) || (n == t2)))
10721 return false;
10722
10723 // if t2 == 15 then UNPREDICTABLE;
10724 if (t2 == 15)
10725 return false;
10726
10727 break;
10728
10729 default:
10730 return false;
10731 }
10732
10733 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10734 uint32_t Rn = ReadCoreReg(n, &success);
10735 if (!success)
10736 return false;
10737
10738 addr_t offset_addr;
10739 if (add)
10740 offset_addr = Rn + imm32;
10741 else
10742 offset_addr = Rn - imm32;
10743
10744 // address = if index then offset_addr else R[n];
10745 addr_t address;
10746 if (index)
10747 address = offset_addr;
10748 else
10749 address = Rn;
10750
10751 // R[t] = MemA[address,4];
10752 RegisterInfo base_reg;
10753 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10754
10755 EmulateInstruction::Context context;
10756 if (n == 13)
10757 context.type = eContextPopRegisterOffStack;
10758 else
10759 context.type = eContextRegisterLoad;
10760 context.SetAddress(address);
10761
10762 const uint32_t addr_byte_size = GetAddressByteSize();
10763 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
10764 if (!success)
10765 return false;
10766
10767 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
10768 return false;
10769
10770 // R[t2] = MemA[address+4,4];
10771 context.SetAddress(address + 4);
10772 data = MemARead(context, address + 4, addr_byte_size, 0, &success);
10773 if (!success)
10774 return false;
10775
10776 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2,
10777 data))
10778 return false;
10779
10780 // if wback then R[n] = offset_addr;
10781 if (wback) {
10782 context.type = eContextAdjustBaseRegister;
10783 context.SetAddress(offset_addr);
10784
10785 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10786 offset_addr))
10787 return false;
10788 }
10789 }
10790 return true;
10791 }
10792
10793 // A8.6.68 LDRD (register)
10794 // Load Register Dual (register) calculates an address from a base register
10795 // value and a register offset, loads two words from memory, and writes them to
10796 // two registers. It can use offset, post-indexed or pre-indexed addressing.
EmulateLDRDRegister(const uint32_t opcode,const ARMEncoding encoding)10797 bool EmulateInstructionARM::EmulateLDRDRegister(const uint32_t opcode,
10798 const ARMEncoding encoding) {
10799 #if 0
10800 if ConditionPassed() then
10801 EncodingSpecificOperations();
10802 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10803 address = if index then offset_addr else R[n];
10804 R[t] = MemA[address,4];
10805 R[t2] = MemA[address+4,4];
10806 if wback then R[n] = offset_addr;
10807 #endif
10808
10809 bool success = false;
10810
10811 if (ConditionPassed(opcode)) {
10812 uint32_t t;
10813 uint32_t t2;
10814 uint32_t n;
10815 uint32_t m;
10816 bool index;
10817 bool add;
10818 bool wback;
10819
10820 switch (encoding) {
10821 case eEncodingA1:
10822 // if Rt<0> == '1' then UNPREDICTABLE;
10823 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10824 t = Bits32(opcode, 15, 12);
10825 if (BitIsSet(t, 0))
10826 return false;
10827 t2 = t + 1;
10828 n = Bits32(opcode, 19, 16);
10829 m = Bits32(opcode, 3, 0);
10830
10831 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10832 index = BitIsSet(opcode, 24);
10833 add = BitIsSet(opcode, 23);
10834 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10835
10836 // if P == '0' && W == '1' then UNPREDICTABLE;
10837 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
10838 return false;
10839
10840 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10841 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
10842 return false;
10843
10844 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10845 if (wback && ((n == 15) || (n == t) || (n == t2)))
10846 return false;
10847
10848 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10849 if ((ArchVersion() < 6) && wback && (m == n))
10850 return false;
10851 break;
10852
10853 default:
10854 return false;
10855 }
10856
10857 uint32_t Rn = ReadCoreReg(n, &success);
10858 if (!success)
10859 return false;
10860 RegisterInfo base_reg;
10861 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10862
10863 uint32_t Rm = ReadCoreReg(m, &success);
10864 if (!success)
10865 return false;
10866 RegisterInfo offset_reg;
10867 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
10868
10869 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10870 addr_t offset_addr;
10871 if (add)
10872 offset_addr = Rn + Rm;
10873 else
10874 offset_addr = Rn - Rm;
10875
10876 // address = if index then offset_addr else R[n];
10877 addr_t address;
10878 if (index)
10879 address = offset_addr;
10880 else
10881 address = Rn;
10882
10883 EmulateInstruction::Context context;
10884 if (n == 13)
10885 context.type = eContextPopRegisterOffStack;
10886 else
10887 context.type = eContextRegisterLoad;
10888 context.SetAddress(address);
10889
10890 // R[t] = MemA[address,4];
10891 const uint32_t addr_byte_size = GetAddressByteSize();
10892 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
10893 if (!success)
10894 return false;
10895
10896 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
10897 return false;
10898
10899 // R[t2] = MemA[address+4,4];
10900
10901 data = MemARead(context, address + 4, addr_byte_size, 0, &success);
10902 if (!success)
10903 return false;
10904
10905 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2,
10906 data))
10907 return false;
10908
10909 // if wback then R[n] = offset_addr;
10910 if (wback) {
10911 context.type = eContextAdjustBaseRegister;
10912 context.SetAddress(offset_addr);
10913
10914 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10915 offset_addr))
10916 return false;
10917 }
10918 }
10919 return true;
10920 }
10921
10922 // A8.6.200 STRD (immediate)
10923 // Store Register Dual (immediate) calculates an address from a base register
10924 // value and an immediate offset, and stores two words from two registers to
10925 // memory. It can use offset, post-indexed, or pre-indexed addressing.
EmulateSTRDImm(const uint32_t opcode,const ARMEncoding encoding)10926 bool EmulateInstructionARM::EmulateSTRDImm(const uint32_t opcode,
10927 const ARMEncoding encoding) {
10928 #if 0
10929 if ConditionPassed() then
10930 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10931 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10932 address = if index then offset_addr else R[n];
10933 MemA[address,4] = R[t];
10934 MemA[address+4,4] = R[t2];
10935 if wback then R[n] = offset_addr;
10936 #endif
10937
10938 bool success = false;
10939
10940 if (ConditionPassed(opcode)) {
10941 uint32_t t;
10942 uint32_t t2;
10943 uint32_t n;
10944 uint32_t imm32;
10945 bool index;
10946 bool add;
10947 bool wback;
10948
10949 switch (encoding) {
10950 case eEncodingT1:
10951 // if P == '0' && W == '0' then SEE 'Related encodings';
10952 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 =
10953 // ZeroExtend(imm8:'00', 32);
10954 t = Bits32(opcode, 15, 12);
10955 t2 = Bits32(opcode, 11, 8);
10956 n = Bits32(opcode, 19, 16);
10957 imm32 = Bits32(opcode, 7, 0) << 2;
10958
10959 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
10960 index = BitIsSet(opcode, 24);
10961 add = BitIsSet(opcode, 23);
10962 wback = BitIsSet(opcode, 21);
10963
10964 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10965 if (wback && ((n == t) || (n == t2)))
10966 return false;
10967
10968 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
10969 if ((n == 15) || BadReg(t) || BadReg(t2))
10970 return false;
10971
10972 break;
10973
10974 case eEncodingA1:
10975 // if Rt<0> == '1' then UNPREDICTABLE;
10976 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L,
10977 // 32);
10978 t = Bits32(opcode, 15, 12);
10979 if (BitIsSet(t, 0))
10980 return false;
10981
10982 t2 = t + 1;
10983 n = Bits32(opcode, 19, 16);
10984 imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0);
10985
10986 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10987 index = BitIsSet(opcode, 24);
10988 add = BitIsSet(opcode, 23);
10989 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10990
10991 // if P == '0' && W == '1' then UNPREDICTABLE;
10992 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
10993 return false;
10994
10995 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10996 if (wback && ((n == 15) || (n == t) || (n == t2)))
10997 return false;
10998
10999 // if t2 == 15 then UNPREDICTABLE;
11000 if (t2 == 15)
11001 return false;
11002
11003 break;
11004
11005 default:
11006 return false;
11007 }
11008
11009 RegisterInfo base_reg;
11010 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11011
11012 uint32_t Rn = ReadCoreReg(n, &success);
11013 if (!success)
11014 return false;
11015
11016 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
11017 addr_t offset_addr;
11018 if (add)
11019 offset_addr = Rn + imm32;
11020 else
11021 offset_addr = Rn - imm32;
11022
11023 // address = if index then offset_addr else R[n];
11024 addr_t address;
11025 if (index)
11026 address = offset_addr;
11027 else
11028 address = Rn;
11029
11030 // MemA[address,4] = R[t];
11031 RegisterInfo data_reg;
11032 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
11033
11034 uint32_t data = ReadCoreReg(t, &success);
11035 if (!success)
11036 return false;
11037
11038 EmulateInstruction::Context context;
11039 if (n == 13)
11040 context.type = eContextPushRegisterOnStack;
11041 else
11042 context.type = eContextRegisterStore;
11043 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
11044
11045 const uint32_t addr_byte_size = GetAddressByteSize();
11046
11047 if (!MemAWrite(context, address, data, addr_byte_size))
11048 return false;
11049
11050 // MemA[address+4,4] = R[t2];
11051 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
11052 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11053 (address + 4) - Rn);
11054
11055 data = ReadCoreReg(t2, &success);
11056 if (!success)
11057 return false;
11058
11059 if (!MemAWrite(context, address + 4, data, addr_byte_size))
11060 return false;
11061
11062 // if wback then R[n] = offset_addr;
11063 if (wback) {
11064 if (n == 13)
11065 context.type = eContextAdjustStackPointer;
11066 else
11067 context.type = eContextAdjustBaseRegister;
11068 context.SetAddress(offset_addr);
11069
11070 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11071 offset_addr))
11072 return false;
11073 }
11074 }
11075 return true;
11076 }
11077
11078 // A8.6.201 STRD (register)
EmulateSTRDReg(const uint32_t opcode,const ARMEncoding encoding)11079 bool EmulateInstructionARM::EmulateSTRDReg(const uint32_t opcode,
11080 const ARMEncoding encoding) {
11081 #if 0
11082 if ConditionPassed() then
11083 EncodingSpecificOperations();
11084 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
11085 address = if index then offset_addr else R[n];
11086 MemA[address,4] = R[t];
11087 MemA[address+4,4] = R[t2];
11088 if wback then R[n] = offset_addr;
11089 #endif
11090
11091 bool success = false;
11092
11093 if (ConditionPassed(opcode)) {
11094 uint32_t t;
11095 uint32_t t2;
11096 uint32_t n;
11097 uint32_t m;
11098 bool index;
11099 bool add;
11100 bool wback;
11101
11102 switch (encoding) {
11103 case eEncodingA1:
11104 // if Rt<0> == '1' then UNPREDICTABLE;
11105 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
11106 t = Bits32(opcode, 15, 12);
11107 if (BitIsSet(t, 0))
11108 return false;
11109
11110 t2 = t + 1;
11111 n = Bits32(opcode, 19, 16);
11112 m = Bits32(opcode, 3, 0);
11113
11114 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
11115 index = BitIsSet(opcode, 24);
11116 add = BitIsSet(opcode, 23);
11117 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
11118
11119 // if P == '0' && W == '1' then UNPREDICTABLE;
11120 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
11121 return false;
11122
11123 // if t2 == 15 || m == 15 then UNPREDICTABLE;
11124 if ((t2 == 15) || (m == 15))
11125 return false;
11126
11127 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
11128 if (wback && ((n == 15) || (n == t) || (n == t2)))
11129 return false;
11130
11131 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
11132 if ((ArchVersion() < 6) && wback && (m == n))
11133 return false;
11134
11135 break;
11136
11137 default:
11138 return false;
11139 }
11140
11141 RegisterInfo base_reg;
11142 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11143 RegisterInfo offset_reg;
11144 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
11145 RegisterInfo data_reg;
11146
11147 uint32_t Rn = ReadCoreReg(n, &success);
11148 if (!success)
11149 return false;
11150
11151 uint32_t Rm = ReadCoreReg(m, &success);
11152 if (!success)
11153 return false;
11154
11155 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
11156 addr_t offset_addr;
11157 if (add)
11158 offset_addr = Rn + Rm;
11159 else
11160 offset_addr = Rn - Rm;
11161
11162 // address = if index then offset_addr else R[n];
11163 addr_t address;
11164 if (index)
11165 address = offset_addr;
11166 else
11167 address = Rn;
11168 // MemA[address,4] = R[t];
11169 uint32_t Rt = ReadCoreReg(t, &success);
11170 if (!success)
11171 return false;
11172
11173 EmulateInstruction::Context context;
11174 if (t == 13)
11175 context.type = eContextPushRegisterOnStack;
11176 else
11177 context.type = eContextRegisterStore;
11178
11179 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg);
11180 context.SetRegisterToRegisterPlusIndirectOffset(base_reg, offset_reg,
11181 data_reg);
11182
11183 const uint32_t addr_byte_size = GetAddressByteSize();
11184
11185 if (!MemAWrite(context, address, Rt, addr_byte_size))
11186 return false;
11187
11188 // MemA[address+4,4] = R[t2];
11189 uint32_t Rt2 = ReadCoreReg(t2, &success);
11190 if (!success)
11191 return false;
11192
11193 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
11194
11195 context.SetRegisterToRegisterPlusIndirectOffset(base_reg, offset_reg,
11196 data_reg);
11197
11198 if (!MemAWrite(context, address + 4, Rt2, addr_byte_size))
11199 return false;
11200
11201 // if wback then R[n] = offset_addr;
11202 if (wback) {
11203 context.type = eContextAdjustBaseRegister;
11204 context.SetAddress(offset_addr);
11205
11206 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11207 offset_addr))
11208 return false;
11209 }
11210 }
11211 return true;
11212 }
11213
11214 // A8.6.319 VLDM
11215 // Vector Load Multiple loads multiple extension registers from consecutive
11216 // memory locations using an address from an ARM core register.
EmulateVLDM(const uint32_t opcode,const ARMEncoding encoding)11217 bool EmulateInstructionARM::EmulateVLDM(const uint32_t opcode,
11218 const ARMEncoding encoding) {
11219 #if 0
11220 if ConditionPassed() then
11221 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11222 address = if add then R[n] else R[n]-imm32;
11223 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11224 for r = 0 to regs-1
11225 if single_regs then
11226 S[d+r] = MemA[address,4]; address = address+4;
11227 else
11228 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
11229 // Combine the word-aligned words in the correct order for
11230 // current endianness.
11231 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
11232 #endif
11233
11234 bool success = false;
11235
11236 if (ConditionPassed(opcode)) {
11237 bool single_regs;
11238 bool add;
11239 bool wback;
11240 uint32_t d;
11241 uint32_t n;
11242 uint32_t imm32;
11243 uint32_t regs;
11244
11245 switch (encoding) {
11246 case eEncodingT1:
11247 case eEncodingA1:
11248 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11249 // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;
11250 // if P == '1' && W == '0' then SEE VLDR;
11251 // if P == U && W == '1' then UNDEFINED;
11252 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11253 return false;
11254
11255 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11256 // !), 101 (DB with !)
11257 // single_regs = FALSE; add = (U == '1'); wback = (W == '1');
11258 single_regs = false;
11259 add = BitIsSet(opcode, 23);
11260 wback = BitIsSet(opcode, 21);
11261
11262 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
11263 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11264 n = Bits32(opcode, 19, 16);
11265 imm32 = Bits32(opcode, 7, 0) << 2;
11266
11267 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FLDMX'.
11268 regs = Bits32(opcode, 7, 0) / 2;
11269
11270 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11271 // UNPREDICTABLE;
11272 if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
11273 return false;
11274
11275 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
11276 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
11277 return false;
11278
11279 break;
11280
11281 case eEncodingT2:
11282 case eEncodingA2:
11283 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11284 // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;
11285 // if P == '1' && W == '0' then SEE VLDR;
11286 // if P == U && W == '1' then UNDEFINED;
11287 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11288 return false;
11289
11290 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11291 // !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W
11292 // == '1'); d =
11293 // UInt(Vd:D); n = UInt(Rn);
11294 single_regs = true;
11295 add = BitIsSet(opcode, 23);
11296 wback = BitIsSet(opcode, 21);
11297 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11298 n = Bits32(opcode, 19, 16);
11299
11300 // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
11301 imm32 = Bits32(opcode, 7, 0) << 2;
11302 regs = Bits32(opcode, 7, 0);
11303
11304 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11305 // UNPREDICTABLE;
11306 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11307 return false;
11308
11309 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
11310 if ((regs == 0) || ((d + regs) > 32))
11311 return false;
11312 break;
11313
11314 default:
11315 return false;
11316 }
11317
11318 RegisterInfo base_reg;
11319 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11320
11321 uint32_t Rn = ReadCoreReg(n, &success);
11322 if (!success)
11323 return false;
11324
11325 // address = if add then R[n] else R[n]-imm32;
11326 addr_t address;
11327 if (add)
11328 address = Rn;
11329 else
11330 address = Rn - imm32;
11331
11332 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11333 EmulateInstruction::Context context;
11334
11335 if (wback) {
11336 uint32_t value;
11337 if (add)
11338 value = Rn + imm32;
11339 else
11340 value = Rn - imm32;
11341
11342 context.type = eContextAdjustBaseRegister;
11343 context.SetImmediateSigned(value - Rn);
11344 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11345 value))
11346 return false;
11347 }
11348
11349 const uint32_t addr_byte_size = GetAddressByteSize();
11350 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
11351
11352 context.type = eContextRegisterLoad;
11353
11354 // for r = 0 to regs-1
11355 for (uint32_t r = 0; r < regs; ++r) {
11356 if (single_regs) {
11357 // S[d+r] = MemA[address,4]; address = address+4;
11358 context.SetRegisterPlusOffset(base_reg, address - Rn);
11359
11360 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
11361 if (!success)
11362 return false;
11363
11364 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
11365 start_reg + d + r, data))
11366 return false;
11367
11368 address = address + 4;
11369 } else {
11370 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address =
11371 // address+8;
11372 context.SetRegisterPlusOffset(base_reg, address - Rn);
11373 uint32_t word1 =
11374 MemARead(context, address, addr_byte_size, 0, &success);
11375 if (!success)
11376 return false;
11377
11378 context.SetRegisterPlusOffset(base_reg, (address + 4) - Rn);
11379 uint32_t word2 =
11380 MemARead(context, address + 4, addr_byte_size, 0, &success);
11381 if (!success)
11382 return false;
11383
11384 address = address + 8;
11385 // // Combine the word-aligned words in the correct order for current
11386 // endianness.
11387 // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
11388 uint64_t data;
11389 if (GetByteOrder() == eByteOrderBig) {
11390 data = word1;
11391 data = (data << 32) | word2;
11392 } else {
11393 data = word2;
11394 data = (data << 32) | word1;
11395 }
11396
11397 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
11398 start_reg + d + r, data))
11399 return false;
11400 }
11401 }
11402 }
11403 return true;
11404 }
11405
11406 // A8.6.399 VSTM
11407 // Vector Store Multiple stores multiple extension registers to consecutive
11408 // memory locations using an address from an
11409 // ARM core register.
EmulateVSTM(const uint32_t opcode,const ARMEncoding encoding)11410 bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode,
11411 const ARMEncoding encoding) {
11412 #if 0
11413 if ConditionPassed() then
11414 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11415 address = if add then R[n] else R[n]-imm32;
11416 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11417 for r = 0 to regs-1
11418 if single_regs then
11419 MemA[address,4] = S[d+r]; address = address+4;
11420 else
11421 // Store as two word-aligned words in the correct order for
11422 // current endianness.
11423 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
11424 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
11425 address = address+8;
11426 #endif
11427
11428 bool success = false;
11429
11430 if (ConditionPassed(opcode)) {
11431 bool single_regs;
11432 bool add;
11433 bool wback;
11434 uint32_t d;
11435 uint32_t n;
11436 uint32_t imm32;
11437 uint32_t regs;
11438
11439 switch (encoding) {
11440 case eEncodingT1:
11441 case eEncodingA1:
11442 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11443 // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;
11444 // if P == '1' && W == '0' then SEE VSTR;
11445 // if P == U && W == '1' then UNDEFINED;
11446 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11447 return false;
11448
11449 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11450 // !), 101 (DB with !)
11451 // single_regs = FALSE; add = (U == '1'); wback = (W == '1');
11452 single_regs = false;
11453 add = BitIsSet(opcode, 23);
11454 wback = BitIsSet(opcode, 21);
11455
11456 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
11457 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11458 n = Bits32(opcode, 19, 16);
11459 imm32 = Bits32(opcode, 7, 0) << 2;
11460
11461 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FSTMX'.
11462 regs = Bits32(opcode, 7, 0) / 2;
11463
11464 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11465 // UNPREDICTABLE;
11466 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11467 return false;
11468
11469 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
11470 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
11471 return false;
11472
11473 break;
11474
11475 case eEncodingT2:
11476 case eEncodingA2:
11477 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11478 // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;
11479 // if P == '1' && W == '0' then SEE VSTR;
11480 // if P == U && W == '1' then UNDEFINED;
11481 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11482 return false;
11483
11484 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11485 // !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W
11486 // == '1'); d =
11487 // UInt(Vd:D); n = UInt(Rn);
11488 single_regs = true;
11489 add = BitIsSet(opcode, 23);
11490 wback = BitIsSet(opcode, 21);
11491 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11492 n = Bits32(opcode, 19, 16);
11493
11494 // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
11495 imm32 = Bits32(opcode, 7, 0) << 2;
11496 regs = Bits32(opcode, 7, 0);
11497
11498 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11499 // UNPREDICTABLE;
11500 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11501 return false;
11502
11503 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
11504 if ((regs == 0) || ((d + regs) > 32))
11505 return false;
11506
11507 break;
11508
11509 default:
11510 return false;
11511 }
11512
11513 RegisterInfo base_reg;
11514 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11515
11516 uint32_t Rn = ReadCoreReg(n, &success);
11517 if (!success)
11518 return false;
11519
11520 // address = if add then R[n] else R[n]-imm32;
11521 addr_t address;
11522 if (add)
11523 address = Rn;
11524 else
11525 address = Rn - imm32;
11526
11527 EmulateInstruction::Context context;
11528 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11529 if (wback) {
11530 uint32_t value;
11531 if (add)
11532 value = Rn + imm32;
11533 else
11534 value = Rn - imm32;
11535
11536 context.type = eContextAdjustBaseRegister;
11537 context.SetRegisterPlusOffset(base_reg, value - Rn);
11538
11539 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11540 value))
11541 return false;
11542 }
11543
11544 const uint32_t addr_byte_size = GetAddressByteSize();
11545 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
11546
11547 context.type = eContextRegisterStore;
11548 // for r = 0 to regs-1
11549 for (uint32_t r = 0; r < regs; ++r) {
11550
11551 if (single_regs) {
11552 // MemA[address,4] = S[d+r]; address = address+4;
11553 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF,
11554 start_reg + d + r, 0, &success);
11555 if (!success)
11556 return false;
11557
11558 RegisterInfo data_reg;
11559 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r, data_reg);
11560 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11561 address - Rn);
11562 if (!MemAWrite(context, address, data, addr_byte_size))
11563 return false;
11564
11565 address = address + 4;
11566 } else {
11567 // // Store as two word-aligned words in the correct order for current
11568 // endianness. MemA[address,4] = if BigEndian() then D[d+r]<63:32> else
11569 // D[d+r]<31:0>;
11570 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else
11571 // D[d+r]<63:32>;
11572 uint64_t data = ReadRegisterUnsigned(eRegisterKindDWARF,
11573 start_reg + d + r, 0, &success);
11574 if (!success)
11575 return false;
11576
11577 RegisterInfo data_reg;
11578 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r, data_reg);
11579
11580 if (GetByteOrder() == eByteOrderBig) {
11581 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11582 address - Rn);
11583 if (!MemAWrite(context, address, Bits64(data, 63, 32),
11584 addr_byte_size))
11585 return false;
11586
11587 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11588 (address + 4) - Rn);
11589 if (!MemAWrite(context, address + 4, Bits64(data, 31, 0),
11590 addr_byte_size))
11591 return false;
11592 } else {
11593 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11594 address - Rn);
11595 if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size))
11596 return false;
11597
11598 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11599 (address + 4) - Rn);
11600 if (!MemAWrite(context, address + 4, Bits64(data, 63, 32),
11601 addr_byte_size))
11602 return false;
11603 }
11604 // address = address+8;
11605 address = address + 8;
11606 }
11607 }
11608 }
11609 return true;
11610 }
11611
11612 // A8.6.320
11613 // This instruction loads a single extension register from memory, using an
11614 // address from an ARM core register, with an optional offset.
EmulateVLDR(const uint32_t opcode,ARMEncoding encoding)11615 bool EmulateInstructionARM::EmulateVLDR(const uint32_t opcode,
11616 ARMEncoding encoding) {
11617 #if 0
11618 if ConditionPassed() then
11619 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11620 base = if n == 15 then Align(PC,4) else R[n];
11621 address = if add then (base + imm32) else (base - imm32);
11622 if single_reg then
11623 S[d] = MemA[address,4];
11624 else
11625 word1 = MemA[address,4]; word2 = MemA[address+4,4];
11626 // Combine the word-aligned words in the correct order for current
11627 // endianness.
11628 D[d] = if BigEndian() then word1:word2 else word2:word1;
11629 #endif
11630
11631 bool success = false;
11632
11633 if (ConditionPassed(opcode)) {
11634 bool single_reg;
11635 bool add;
11636 uint32_t imm32;
11637 uint32_t d;
11638 uint32_t n;
11639
11640 switch (encoding) {
11641 case eEncodingT1:
11642 case eEncodingA1:
11643 // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00',
11644 // 32);
11645 single_reg = false;
11646 add = BitIsSet(opcode, 23);
11647 imm32 = Bits32(opcode, 7, 0) << 2;
11648
11649 // d = UInt(D:Vd); n = UInt(Rn);
11650 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11651 n = Bits32(opcode, 19, 16);
11652
11653 break;
11654
11655 case eEncodingT2:
11656 case eEncodingA2:
11657 // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
11658 single_reg = true;
11659 add = BitIsSet(opcode, 23);
11660 imm32 = Bits32(opcode, 7, 0) << 2;
11661
11662 // d = UInt(Vd:D); n = UInt(Rn);
11663 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11664 n = Bits32(opcode, 19, 16);
11665
11666 break;
11667
11668 default:
11669 return false;
11670 }
11671 RegisterInfo base_reg;
11672 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11673
11674 uint32_t Rn = ReadCoreReg(n, &success);
11675 if (!success)
11676 return false;
11677
11678 // base = if n == 15 then Align(PC,4) else R[n];
11679 uint32_t base;
11680 if (n == 15)
11681 base = AlignPC(Rn);
11682 else
11683 base = Rn;
11684
11685 // address = if add then (base + imm32) else (base - imm32);
11686 addr_t address;
11687 if (add)
11688 address = base + imm32;
11689 else
11690 address = base - imm32;
11691
11692 const uint32_t addr_byte_size = GetAddressByteSize();
11693 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11694
11695 EmulateInstruction::Context context;
11696 context.type = eContextRegisterLoad;
11697 context.SetRegisterPlusOffset(base_reg, address - base);
11698
11699 if (single_reg) {
11700 // S[d] = MemA[address,4];
11701 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
11702 if (!success)
11703 return false;
11704
11705 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d,
11706 data))
11707 return false;
11708 } else {
11709 // word1 = MemA[address,4]; word2 = MemA[address+4,4];
11710 uint32_t word1 = MemARead(context, address, addr_byte_size, 0, &success);
11711 if (!success)
11712 return false;
11713
11714 context.SetRegisterPlusOffset(base_reg, (address + 4) - base);
11715 uint32_t word2 =
11716 MemARead(context, address + 4, addr_byte_size, 0, &success);
11717 if (!success)
11718 return false;
11719 // // Combine the word-aligned words in the correct order for current
11720 // endianness.
11721 // D[d] = if BigEndian() then word1:word2 else word2:word1;
11722 uint64_t data64;
11723 if (GetByteOrder() == eByteOrderBig) {
11724 data64 = word1;
11725 data64 = (data64 << 32) | word2;
11726 } else {
11727 data64 = word2;
11728 data64 = (data64 << 32) | word1;
11729 }
11730
11731 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d,
11732 data64))
11733 return false;
11734 }
11735 }
11736 return true;
11737 }
11738
11739 // A8.6.400 VSTR
11740 // This instruction stores a signle extension register to memory, using an
11741 // address from an ARM core register, with an optional offset.
EmulateVSTR(const uint32_t opcode,ARMEncoding encoding)11742 bool EmulateInstructionARM::EmulateVSTR(const uint32_t opcode,
11743 ARMEncoding encoding) {
11744 #if 0
11745 if ConditionPassed() then
11746 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11747 address = if add then (R[n] + imm32) else (R[n] - imm32);
11748 if single_reg then
11749 MemA[address,4] = S[d];
11750 else
11751 // Store as two word-aligned words in the correct order for current
11752 // endianness.
11753 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11754 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11755 #endif
11756
11757 bool success = false;
11758
11759 if (ConditionPassed(opcode)) {
11760 bool single_reg;
11761 bool add;
11762 uint32_t imm32;
11763 uint32_t d;
11764 uint32_t n;
11765
11766 switch (encoding) {
11767 case eEncodingT1:
11768 case eEncodingA1:
11769 // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00',
11770 // 32);
11771 single_reg = false;
11772 add = BitIsSet(opcode, 23);
11773 imm32 = Bits32(opcode, 7, 0) << 2;
11774
11775 // d = UInt(D:Vd); n = UInt(Rn);
11776 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11777 n = Bits32(opcode, 19, 16);
11778
11779 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11780 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11781 return false;
11782
11783 break;
11784
11785 case eEncodingT2:
11786 case eEncodingA2:
11787 // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
11788 single_reg = true;
11789 add = BitIsSet(opcode, 23);
11790 imm32 = Bits32(opcode, 7, 0) << 2;
11791
11792 // d = UInt(Vd:D); n = UInt(Rn);
11793 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11794 n = Bits32(opcode, 19, 16);
11795
11796 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11797 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11798 return false;
11799
11800 break;
11801
11802 default:
11803 return false;
11804 }
11805
11806 RegisterInfo base_reg;
11807 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11808
11809 uint32_t Rn = ReadCoreReg(n, &success);
11810 if (!success)
11811 return false;
11812
11813 // address = if add then (R[n] + imm32) else (R[n] - imm32);
11814 addr_t address;
11815 if (add)
11816 address = Rn + imm32;
11817 else
11818 address = Rn - imm32;
11819
11820 const uint32_t addr_byte_size = GetAddressByteSize();
11821 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11822
11823 RegisterInfo data_reg;
11824 GetRegisterInfo(eRegisterKindDWARF, start_reg + d, data_reg);
11825 EmulateInstruction::Context context;
11826 context.type = eContextRegisterStore;
11827 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
11828
11829 if (single_reg) {
11830 // MemA[address,4] = S[d];
11831 uint32_t data =
11832 ReadRegisterUnsigned(eRegisterKindDWARF, start_reg + d, 0, &success);
11833 if (!success)
11834 return false;
11835
11836 if (!MemAWrite(context, address, data, addr_byte_size))
11837 return false;
11838 } else {
11839 // // Store as two word-aligned words in the correct order for current
11840 // endianness.
11841 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11842 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11843 uint64_t data =
11844 ReadRegisterUnsigned(eRegisterKindDWARF, start_reg + d, 0, &success);
11845 if (!success)
11846 return false;
11847
11848 if (GetByteOrder() == eByteOrderBig) {
11849 if (!MemAWrite(context, address, Bits64(data, 63, 32), addr_byte_size))
11850 return false;
11851
11852 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11853 (address + 4) - Rn);
11854 if (!MemAWrite(context, address + 4, Bits64(data, 31, 0),
11855 addr_byte_size))
11856 return false;
11857 } else {
11858 if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size))
11859 return false;
11860
11861 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
11862 (address + 4) - Rn);
11863 if (!MemAWrite(context, address + 4, Bits64(data, 63, 32),
11864 addr_byte_size))
11865 return false;
11866 }
11867 }
11868 }
11869 return true;
11870 }
11871
11872 // A8.6.307 VLDI1 (multiple single elements) This instruction loads elements
11873 // from memory into one, two, three or four registers, without de-interleaving.
11874 // Every element of each register is loaded.
EmulateVLD1Multiple(const uint32_t opcode,ARMEncoding encoding)11875 bool EmulateInstructionARM::EmulateVLD1Multiple(const uint32_t opcode,
11876 ARMEncoding encoding) {
11877 #if 0
11878 if ConditionPassed() then
11879 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11880 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11881 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11882 for r = 0 to regs-1
11883 for e = 0 to elements-1
11884 Elem[D[d+r],e,esize] = MemU[address,ebytes];
11885 address = address + ebytes;
11886 #endif
11887
11888 bool success = false;
11889
11890 if (ConditionPassed(opcode)) {
11891 uint32_t regs;
11892 uint32_t alignment;
11893 uint32_t ebytes;
11894 uint32_t esize;
11895 uint32_t elements;
11896 uint32_t d;
11897 uint32_t n;
11898 uint32_t m;
11899 bool wback;
11900 bool register_index;
11901
11902 switch (encoding) {
11903 case eEncodingT1:
11904 case eEncodingA1: {
11905 // case type of
11906 // when '0111'
11907 // regs = 1; if align<1> == '1' then UNDEFINED;
11908 // when '1010'
11909 // regs = 2; if align == '11' then UNDEFINED;
11910 // when '0110'
11911 // regs = 3; if align<1> == '1' then UNDEFINED;
11912 // when '0010'
11913 // regs = 4;
11914 // otherwise
11915 // SEE 'Related encodings';
11916 uint32_t type = Bits32(opcode, 11, 8);
11917 uint32_t align = Bits32(opcode, 5, 4);
11918 if (type == 7) // '0111'
11919 {
11920 regs = 1;
11921 if (BitIsSet(align, 1))
11922 return false;
11923 } else if (type == 10) // '1010'
11924 {
11925 regs = 2;
11926 if (align == 3)
11927 return false;
11928
11929 } else if (type == 6) // '0110'
11930 {
11931 regs = 3;
11932 if (BitIsSet(align, 1))
11933 return false;
11934 } else if (type == 2) // '0010'
11935 {
11936 regs = 4;
11937 } else
11938 return false;
11939
11940 // alignment = if align == '00' then 1 else 4 << UInt(align);
11941 if (align == 0)
11942 alignment = 1;
11943 else
11944 alignment = 4 << align;
11945
11946 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11947 ebytes = 1 << Bits32(opcode, 7, 6);
11948 esize = 8 * ebytes;
11949 elements = 8 / ebytes;
11950
11951 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11952 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11953 n = Bits32(opcode, 19, 15);
11954 m = Bits32(opcode, 3, 0);
11955
11956 // wback = (m != 15); register_index = (m != 15 && m != 13);
11957 wback = (m != 15);
11958 register_index = ((m != 15) && (m != 13));
11959
11960 // if d+regs > 32 then UNPREDICTABLE;
11961 if ((d + regs) > 32)
11962 return false;
11963 } break;
11964
11965 default:
11966 return false;
11967 }
11968
11969 RegisterInfo base_reg;
11970 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11971
11972 uint32_t Rn = ReadCoreReg(n, &success);
11973 if (!success)
11974 return false;
11975
11976 // address = R[n]; if (address MOD alignment) != 0 then
11977 // GenerateAlignmentException();
11978 addr_t address = Rn;
11979 if ((address % alignment) != 0)
11980 return false;
11981
11982 EmulateInstruction::Context context;
11983 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11984 if (wback) {
11985 uint32_t Rm = ReadCoreReg(m, &success);
11986 if (!success)
11987 return false;
11988
11989 uint32_t offset;
11990 if (register_index)
11991 offset = Rm;
11992 else
11993 offset = 8 * regs;
11994
11995 uint32_t value = Rn + offset;
11996 context.type = eContextAdjustBaseRegister;
11997 context.SetRegisterPlusOffset(base_reg, offset);
11998
11999 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12000 value))
12001 return false;
12002 }
12003
12004 // for r = 0 to regs-1
12005 for (uint32_t r = 0; r < regs; ++r) {
12006 // for e = 0 to elements-1
12007 uint64_t assembled_data = 0;
12008 for (uint32_t e = 0; e < elements; ++e) {
12009 // Elem[D[d+r],e,esize] = MemU[address,ebytes];
12010 context.type = eContextRegisterLoad;
12011 context.SetRegisterPlusOffset(base_reg, address - Rn);
12012 uint64_t data = MemURead(context, address, ebytes, 0, &success);
12013 if (!success)
12014 return false;
12015
12016 assembled_data =
12017 (data << (e * esize)) |
12018 assembled_data; // New data goes to the left of existing data
12019
12020 // address = address + ebytes;
12021 address = address + ebytes;
12022 }
12023 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_d0 + d + r,
12024 assembled_data))
12025 return false;
12026 }
12027 }
12028 return true;
12029 }
12030
12031 // A8.6.308 VLD1 (single element to one lane)
12032 //
EmulateVLD1Single(const uint32_t opcode,const ARMEncoding encoding)12033 bool EmulateInstructionARM::EmulateVLD1Single(const uint32_t opcode,
12034 const ARMEncoding encoding) {
12035 #if 0
12036 if ConditionPassed() then
12037 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12038 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12039 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12040 Elem[D[d],index,esize] = MemU[address,ebytes];
12041 #endif
12042
12043 bool success = false;
12044
12045 if (ConditionPassed(opcode)) {
12046 uint32_t ebytes;
12047 uint32_t esize;
12048 uint32_t index;
12049 uint32_t alignment;
12050 uint32_t d;
12051 uint32_t n;
12052 uint32_t m;
12053 bool wback;
12054 bool register_index;
12055
12056 switch (encoding) {
12057 case eEncodingT1:
12058 case eEncodingA1: {
12059 uint32_t size = Bits32(opcode, 11, 10);
12060 uint32_t index_align = Bits32(opcode, 7, 4);
12061 // if size == '11' then SEE VLD1 (single element to all lanes);
12062 if (size == 3)
12063 return EmulateVLD1SingleAll(opcode, encoding);
12064 // case size of
12065 if (size == 0) // when '00'
12066 {
12067 // if index_align<0> != '0' then UNDEFINED;
12068 if (BitIsClear(index_align, 0))
12069 return false;
12070
12071 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
12072 ebytes = 1;
12073 esize = 8;
12074 index = Bits32(index_align, 3, 1);
12075 alignment = 1;
12076 } else if (size == 1) // when '01'
12077 {
12078 // if index_align<1> != '0' then UNDEFINED;
12079 if (BitIsClear(index_align, 1))
12080 return false;
12081
12082 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
12083 ebytes = 2;
12084 esize = 16;
12085 index = Bits32(index_align, 3, 2);
12086
12087 // alignment = if index_align<0> == '0' then 1 else 2;
12088 if (BitIsClear(index_align, 0))
12089 alignment = 1;
12090 else
12091 alignment = 2;
12092 } else if (size == 2) // when '10'
12093 {
12094 // if index_align<2> != '0' then UNDEFINED;
12095 if (BitIsClear(index_align, 2))
12096 return false;
12097
12098 // if index_align<1:0> != '00' && index_align<1:0> != '11' then
12099 // UNDEFINED;
12100 if ((Bits32(index_align, 1, 0) != 0) &&
12101 (Bits32(index_align, 1, 0) != 3))
12102 return false;
12103
12104 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
12105 ebytes = 4;
12106 esize = 32;
12107 index = Bit32(index_align, 3);
12108
12109 // alignment = if index_align<1:0> == '00' then 1 else 4;
12110 if (Bits32(index_align, 1, 0) == 0)
12111 alignment = 1;
12112 else
12113 alignment = 4;
12114 } else {
12115 return false;
12116 }
12117 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12118 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12119 n = Bits32(opcode, 19, 16);
12120 m = Bits32(opcode, 3, 0);
12121
12122 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15
12123 // then UNPREDICTABLE;
12124 wback = (m != 15);
12125 register_index = ((m != 15) && (m != 13));
12126
12127 if (n == 15)
12128 return false;
12129
12130 } break;
12131
12132 default:
12133 return false;
12134 }
12135
12136 RegisterInfo base_reg;
12137 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
12138
12139 uint32_t Rn = ReadCoreReg(n, &success);
12140 if (!success)
12141 return false;
12142
12143 // address = R[n]; if (address MOD alignment) != 0 then
12144 // GenerateAlignmentException();
12145 addr_t address = Rn;
12146 if ((address % alignment) != 0)
12147 return false;
12148
12149 EmulateInstruction::Context context;
12150 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12151 if (wback) {
12152 uint32_t Rm = ReadCoreReg(m, &success);
12153 if (!success)
12154 return false;
12155
12156 uint32_t offset;
12157 if (register_index)
12158 offset = Rm;
12159 else
12160 offset = ebytes;
12161
12162 uint32_t value = Rn + offset;
12163
12164 context.type = eContextAdjustBaseRegister;
12165 context.SetRegisterPlusOffset(base_reg, offset);
12166
12167 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12168 value))
12169 return false;
12170 }
12171
12172 // Elem[D[d],index,esize] = MemU[address,ebytes];
12173 uint32_t element = MemURead(context, address, esize, 0, &success);
12174 if (!success)
12175 return false;
12176
12177 element = element << (index * esize);
12178
12179 uint64_t reg_data =
12180 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
12181 if (!success)
12182 return false;
12183
12184 uint64_t all_ones = -1;
12185 uint64_t mask = all_ones
12186 << ((index + 1) * esize); // mask is all 1's to left of
12187 // where 'element' goes, & all 0's
12188 // at element & to the right of element.
12189 if (index > 0)
12190 mask = mask | Bits64(all_ones, (index * esize) - 1,
12191 0); // add 1's to the right of where 'element' goes.
12192 // now mask should be 0's where element goes & 1's everywhere else.
12193
12194 uint64_t masked_reg =
12195 reg_data & mask; // Take original reg value & zero out 'element' bits
12196 reg_data =
12197 masked_reg & element; // Put 'element' into those bits in reg_data.
12198
12199 context.type = eContextRegisterLoad;
12200 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
12201 reg_data))
12202 return false;
12203 }
12204 return true;
12205 }
12206
12207 // A8.6.391 VST1 (multiple single elements) Vector Store (multiple single
12208 // elements) stores elements to memory from one, two, three, or four registers,
12209 // without interleaving. Every element of each register is stored.
EmulateVST1Multiple(const uint32_t opcode,ARMEncoding encoding)12210 bool EmulateInstructionARM::EmulateVST1Multiple(const uint32_t opcode,
12211 ARMEncoding encoding) {
12212 #if 0
12213 if ConditionPassed() then
12214 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12215 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12216 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
12217 for r = 0 to regs-1
12218 for e = 0 to elements-1
12219 MemU[address,ebytes] = Elem[D[d+r],e,esize];
12220 address = address + ebytes;
12221 #endif
12222
12223 bool success = false;
12224
12225 if (ConditionPassed(opcode)) {
12226 uint32_t regs;
12227 uint32_t alignment;
12228 uint32_t ebytes;
12229 uint32_t esize;
12230 uint32_t elements;
12231 uint32_t d;
12232 uint32_t n;
12233 uint32_t m;
12234 bool wback;
12235 bool register_index;
12236
12237 switch (encoding) {
12238 case eEncodingT1:
12239 case eEncodingA1: {
12240 uint32_t type = Bits32(opcode, 11, 8);
12241 uint32_t align = Bits32(opcode, 5, 4);
12242
12243 // case type of
12244 if (type == 7) // when '0111'
12245 {
12246 // regs = 1; if align<1> == '1' then UNDEFINED;
12247 regs = 1;
12248 if (BitIsSet(align, 1))
12249 return false;
12250 } else if (type == 10) // when '1010'
12251 {
12252 // regs = 2; if align == '11' then UNDEFINED;
12253 regs = 2;
12254 if (align == 3)
12255 return false;
12256 } else if (type == 6) // when '0110'
12257 {
12258 // regs = 3; if align<1> == '1' then UNDEFINED;
12259 regs = 3;
12260 if (BitIsSet(align, 1))
12261 return false;
12262 } else if (type == 2) // when '0010'
12263 // regs = 4;
12264 regs = 4;
12265 else // otherwise
12266 // SEE 'Related encodings';
12267 return false;
12268
12269 // alignment = if align == '00' then 1 else 4 << UInt(align);
12270 if (align == 0)
12271 alignment = 1;
12272 else
12273 alignment = 4 << align;
12274
12275 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
12276 ebytes = 1 << Bits32(opcode, 7, 6);
12277 esize = 8 * ebytes;
12278 elements = 8 / ebytes;
12279
12280 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12281 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12282 n = Bits32(opcode, 19, 16);
12283 m = Bits32(opcode, 3, 0);
12284
12285 // wback = (m != 15); register_index = (m != 15 && m != 13);
12286 wback = (m != 15);
12287 register_index = ((m != 15) && (m != 13));
12288
12289 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
12290 if ((d + regs) > 32)
12291 return false;
12292
12293 if (n == 15)
12294 return false;
12295
12296 } break;
12297
12298 default:
12299 return false;
12300 }
12301
12302 RegisterInfo base_reg;
12303 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
12304
12305 uint32_t Rn = ReadCoreReg(n, &success);
12306 if (!success)
12307 return false;
12308
12309 // address = R[n]; if (address MOD alignment) != 0 then
12310 // GenerateAlignmentException();
12311 addr_t address = Rn;
12312 if ((address % alignment) != 0)
12313 return false;
12314
12315 EmulateInstruction::Context context;
12316 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
12317 if (wback) {
12318 uint32_t Rm = ReadCoreReg(m, &success);
12319 if (!success)
12320 return false;
12321
12322 uint32_t offset;
12323 if (register_index)
12324 offset = Rm;
12325 else
12326 offset = 8 * regs;
12327
12328 context.type = eContextAdjustBaseRegister;
12329 context.SetRegisterPlusOffset(base_reg, offset);
12330
12331 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12332 Rn + offset))
12333 return false;
12334 }
12335
12336 RegisterInfo data_reg;
12337 context.type = eContextRegisterStore;
12338 // for r = 0 to regs-1
12339 for (uint32_t r = 0; r < regs; ++r) {
12340 GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d + r, data_reg);
12341 uint64_t register_data = ReadRegisterUnsigned(
12342 eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);
12343 if (!success)
12344 return false;
12345
12346 // for e = 0 to elements-1
12347 for (uint32_t e = 0; e < elements; ++e) {
12348 // MemU[address,ebytes] = Elem[D[d+r],e,esize];
12349 uint64_t word = Bits64(register_data, ((e + 1) * esize) - 1, e * esize);
12350
12351 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg,
12352 address - Rn);
12353 if (!MemUWrite(context, address, word, ebytes))
12354 return false;
12355
12356 // address = address + ebytes;
12357 address = address + ebytes;
12358 }
12359 }
12360 }
12361 return true;
12362 }
12363
12364 // A8.6.392 VST1 (single element from one lane) This instruction stores one
12365 // element to memory from one element of a register.
EmulateVST1Single(const uint32_t opcode,ARMEncoding encoding)12366 bool EmulateInstructionARM::EmulateVST1Single(const uint32_t opcode,
12367 ARMEncoding encoding) {
12368 #if 0
12369 if ConditionPassed() then
12370 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12371 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12372 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12373 MemU[address,ebytes] = Elem[D[d],index,esize];
12374 #endif
12375
12376 bool success = false;
12377
12378 if (ConditionPassed(opcode)) {
12379 uint32_t ebytes;
12380 uint32_t esize;
12381 uint32_t index;
12382 uint32_t alignment;
12383 uint32_t d;
12384 uint32_t n;
12385 uint32_t m;
12386 bool wback;
12387 bool register_index;
12388
12389 switch (encoding) {
12390 case eEncodingT1:
12391 case eEncodingA1: {
12392 uint32_t size = Bits32(opcode, 11, 10);
12393 uint32_t index_align = Bits32(opcode, 7, 4);
12394
12395 // if size == '11' then UNDEFINED;
12396 if (size == 3)
12397 return false;
12398
12399 // case size of
12400 if (size == 0) // when '00'
12401 {
12402 // if index_align<0> != '0' then UNDEFINED;
12403 if (BitIsClear(index_align, 0))
12404 return false;
12405 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
12406 ebytes = 1;
12407 esize = 8;
12408 index = Bits32(index_align, 3, 1);
12409 alignment = 1;
12410 } else if (size == 1) // when '01'
12411 {
12412 // if index_align<1> != '0' then UNDEFINED;
12413 if (BitIsClear(index_align, 1))
12414 return false;
12415
12416 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
12417 ebytes = 2;
12418 esize = 16;
12419 index = Bits32(index_align, 3, 2);
12420
12421 // alignment = if index_align<0> == '0' then 1 else 2;
12422 if (BitIsClear(index_align, 0))
12423 alignment = 1;
12424 else
12425 alignment = 2;
12426 } else if (size == 2) // when '10'
12427 {
12428 // if index_align<2> != '0' then UNDEFINED;
12429 if (BitIsClear(index_align, 2))
12430 return false;
12431
12432 // if index_align<1:0> != '00' && index_align<1:0> != '11' then
12433 // UNDEFINED;
12434 if ((Bits32(index_align, 1, 0) != 0) &&
12435 (Bits32(index_align, 1, 0) != 3))
12436 return false;
12437
12438 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
12439 ebytes = 4;
12440 esize = 32;
12441 index = Bit32(index_align, 3);
12442
12443 // alignment = if index_align<1:0> == '00' then 1 else 4;
12444 if (Bits32(index_align, 1, 0) == 0)
12445 alignment = 1;
12446 else
12447 alignment = 4;
12448 } else {
12449 return false;
12450 }
12451 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12452 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12453 n = Bits32(opcode, 19, 16);
12454 m = Bits32(opcode, 3, 0);
12455
12456 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15
12457 // then UNPREDICTABLE;
12458 wback = (m != 15);
12459 register_index = ((m != 15) && (m != 13));
12460
12461 if (n == 15)
12462 return false;
12463 } break;
12464
12465 default:
12466 return false;
12467 }
12468
12469 RegisterInfo base_reg;
12470 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
12471
12472 uint32_t Rn = ReadCoreReg(n, &success);
12473 if (!success)
12474 return false;
12475
12476 // address = R[n]; if (address MOD alignment) != 0 then
12477 // GenerateAlignmentException();
12478 addr_t address = Rn;
12479 if ((address % alignment) != 0)
12480 return false;
12481
12482 EmulateInstruction::Context context;
12483 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12484 if (wback) {
12485 uint32_t Rm = ReadCoreReg(m, &success);
12486 if (!success)
12487 return false;
12488
12489 uint32_t offset;
12490 if (register_index)
12491 offset = Rm;
12492 else
12493 offset = ebytes;
12494
12495 context.type = eContextAdjustBaseRegister;
12496 context.SetRegisterPlusOffset(base_reg, offset);
12497
12498 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12499 Rn + offset))
12500 return false;
12501 }
12502
12503 // MemU[address,ebytes] = Elem[D[d],index,esize];
12504 uint64_t register_data =
12505 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
12506 if (!success)
12507 return false;
12508
12509 uint64_t word =
12510 Bits64(register_data, ((index + 1) * esize) - 1, index * esize);
12511
12512 RegisterInfo data_reg;
12513 GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d, data_reg);
12514 context.type = eContextRegisterStore;
12515 context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn);
12516
12517 if (!MemUWrite(context, address, word, ebytes))
12518 return false;
12519 }
12520 return true;
12521 }
12522
12523 // A8.6.309 VLD1 (single element to all lanes) This instruction loads one
12524 // element from memory into every element of one or two vectors.
EmulateVLD1SingleAll(const uint32_t opcode,const ARMEncoding encoding)12525 bool EmulateInstructionARM::EmulateVLD1SingleAll(const uint32_t opcode,
12526 const ARMEncoding encoding) {
12527 #if 0
12528 if ConditionPassed() then
12529 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12530 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12531 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12532 replicated_element = Replicate(MemU[address,ebytes], elements);
12533 for r = 0 to regs-1
12534 D[d+r] = replicated_element;
12535 #endif
12536
12537 bool success = false;
12538
12539 if (ConditionPassed(opcode)) {
12540 uint32_t ebytes;
12541 uint32_t elements;
12542 uint32_t regs;
12543 uint32_t alignment;
12544 uint32_t d;
12545 uint32_t n;
12546 uint32_t m;
12547 bool wback;
12548 bool register_index;
12549
12550 switch (encoding) {
12551 case eEncodingT1:
12552 case eEncodingA1: {
12553 // if size == '11' || (size == '00' && a == '1') then UNDEFINED;
12554 uint32_t size = Bits32(opcode, 7, 6);
12555 if ((size == 3) || ((size == 0) && BitIsSet(opcode, 4)))
12556 return false;
12557
12558 // ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == '0'
12559 // then 1 else 2;
12560 ebytes = 1 << size;
12561 elements = 8 / ebytes;
12562 if (BitIsClear(opcode, 5))
12563 regs = 1;
12564 else
12565 regs = 2;
12566
12567 // alignment = if a == '0' then 1 else ebytes;
12568 if (BitIsClear(opcode, 4))
12569 alignment = 1;
12570 else
12571 alignment = ebytes;
12572
12573 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12574 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12575 n = Bits32(opcode, 19, 16);
12576 m = Bits32(opcode, 3, 0);
12577
12578 // wback = (m != 15); register_index = (m != 15 && m != 13);
12579 wback = (m != 15);
12580 register_index = ((m != 15) && (m != 13));
12581
12582 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
12583 if ((d + regs) > 32)
12584 return false;
12585
12586 if (n == 15)
12587 return false;
12588 } break;
12589
12590 default:
12591 return false;
12592 }
12593
12594 RegisterInfo base_reg;
12595 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg);
12596
12597 uint32_t Rn = ReadCoreReg(n, &success);
12598 if (!success)
12599 return false;
12600
12601 // address = R[n]; if (address MOD alignment) != 0 then
12602 // GenerateAlignmentException();
12603 addr_t address = Rn;
12604 if ((address % alignment) != 0)
12605 return false;
12606
12607 EmulateInstruction::Context context;
12608 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12609 if (wback) {
12610 uint32_t Rm = ReadCoreReg(m, &success);
12611 if (!success)
12612 return false;
12613
12614 uint32_t offset;
12615 if (register_index)
12616 offset = Rm;
12617 else
12618 offset = ebytes;
12619
12620 context.type = eContextAdjustBaseRegister;
12621 context.SetRegisterPlusOffset(base_reg, offset);
12622
12623 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12624 Rn + offset))
12625 return false;
12626 }
12627
12628 // replicated_element = Replicate(MemU[address,ebytes], elements);
12629
12630 context.type = eContextRegisterLoad;
12631 uint64_t word = MemURead(context, address, ebytes, 0, &success);
12632 if (!success)
12633 return false;
12634
12635 uint64_t replicated_element = 0;
12636 uint32_t esize = ebytes * 8;
12637 for (uint32_t e = 0; e < elements; ++e)
12638 replicated_element =
12639 (replicated_element << esize) | Bits64(word, esize - 1, 0);
12640
12641 // for r = 0 to regs-1
12642 for (uint32_t r = 0; r < regs; ++r) {
12643 // D[d+r] = replicated_element;
12644 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_d0 + d + r,
12645 replicated_element))
12646 return false;
12647 }
12648 }
12649 return true;
12650 }
12651
12652 // B6.2.13 SUBS PC, LR and related instructions The SUBS PC, LR, #<const?
12653 // instruction provides an exception return without the use of the stack. It
12654 // subtracts the immediate constant from the LR, branches to the resulting
12655 // address, and also copies the SPSR to the CPSR.
EmulateSUBSPcLrEtc(const uint32_t opcode,const ARMEncoding encoding)12656 bool EmulateInstructionARM::EmulateSUBSPcLrEtc(const uint32_t opcode,
12657 const ARMEncoding encoding) {
12658 #if 0
12659 if ConditionPassed() then
12660 EncodingSpecificOperations();
12661 if CurrentInstrSet() == InstrSet_ThumbEE then
12662 UNPREDICTABLE;
12663 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
12664 case opcode of
12665 when '0000' result = R[n] AND operand2; // AND
12666 when '0001' result = R[n] EOR operand2; // EOR
12667 when '0010' (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB
12668 when '0011' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB
12669 when '0100' (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD
12670 when '0101' (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12671 when '0110' (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12672 when '0111' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12673 when '1100' result = R[n] OR operand2; // ORR
12674 when '1101' result = operand2; // MOV
12675 when '1110' result = R[n] AND NOT(operand2); // BIC
12676 when '1111' result = NOT(operand2); // MVN
12677 CPSRWriteByInstr(SPSR[], '1111', TRUE);
12678 BranchWritePC(result);
12679 #endif
12680
12681 bool success = false;
12682
12683 if (ConditionPassed(opcode)) {
12684 uint32_t n;
12685 uint32_t m;
12686 uint32_t imm32;
12687 bool register_form;
12688 ARM_ShifterType shift_t;
12689 uint32_t shift_n;
12690 uint32_t code;
12691
12692 switch (encoding) {
12693 case eEncodingT1:
12694 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE n = 14;
12695 // imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = '0010';
12696 // // = SUB
12697 n = 14;
12698 imm32 = Bits32(opcode, 7, 0);
12699 register_form = false;
12700 code = 2;
12701
12702 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
12703 if (InITBlock() && !LastInITBlock())
12704 return false;
12705
12706 break;
12707
12708 case eEncodingA1:
12709 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
12710 n = Bits32(opcode, 19, 16);
12711 imm32 = ARMExpandImm(opcode);
12712 register_form = false;
12713 code = Bits32(opcode, 24, 21);
12714
12715 break;
12716
12717 case eEncodingA2:
12718 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
12719 n = Bits32(opcode, 19, 16);
12720 m = Bits32(opcode, 3, 0);
12721 register_form = true;
12722
12723 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
12724 shift_n = DecodeImmShiftARM(opcode, shift_t);
12725
12726 break;
12727
12728 default:
12729 return false;
12730 }
12731
12732 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C)
12733 // else imm32;
12734 uint32_t operand2;
12735 if (register_form) {
12736 uint32_t Rm = ReadCoreReg(m, &success);
12737 if (!success)
12738 return false;
12739
12740 operand2 = Shift(Rm, shift_t, shift_n, APSR_C, &success);
12741 if (!success)
12742 return false;
12743 } else {
12744 operand2 = imm32;
12745 }
12746
12747 uint32_t Rn = ReadCoreReg(n, &success);
12748 if (!success)
12749 return false;
12750
12751 AddWithCarryResult result;
12752
12753 // case opcode of
12754 switch (code) {
12755 case 0: // when '0000'
12756 // result = R[n] AND operand2; // AND
12757 result.result = Rn & operand2;
12758 break;
12759
12760 case 1: // when '0001'
12761 // result = R[n] EOR operand2; // EOR
12762 result.result = Rn ^ operand2;
12763 break;
12764
12765 case 2: // when '0010'
12766 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB
12767 result = AddWithCarry(Rn, ~(operand2), 1);
12768 break;
12769
12770 case 3: // when '0011'
12771 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB
12772 result = AddWithCarry(~(Rn), operand2, 1);
12773 break;
12774
12775 case 4: // when '0100'
12776 // (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD
12777 result = AddWithCarry(Rn, operand2, 0);
12778 break;
12779
12780 case 5: // when '0101'
12781 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12782 result = AddWithCarry(Rn, operand2, APSR_C);
12783 break;
12784
12785 case 6: // when '0110'
12786 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12787 result = AddWithCarry(Rn, ~(operand2), APSR_C);
12788 break;
12789
12790 case 7: // when '0111'
12791 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12792 result = AddWithCarry(~(Rn), operand2, APSR_C);
12793 break;
12794
12795 case 10: // when '1100'
12796 // result = R[n] OR operand2; // ORR
12797 result.result = Rn | operand2;
12798 break;
12799
12800 case 11: // when '1101'
12801 // result = operand2; // MOV
12802 result.result = operand2;
12803 break;
12804
12805 case 12: // when '1110'
12806 // result = R[n] AND NOT(operand2); // BIC
12807 result.result = Rn & ~(operand2);
12808 break;
12809
12810 case 15: // when '1111'
12811 // result = NOT(operand2); // MVN
12812 result.result = ~(operand2);
12813 break;
12814
12815 default:
12816 return false;
12817 }
12818 // CPSRWriteByInstr(SPSR[], '1111', TRUE);
12819
12820 // For now, in emulation mode, we don't have access to the SPSR, so we will
12821 // use the CPSR instead, and hope for the best.
12822 uint32_t spsr =
12823 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success);
12824 if (!success)
12825 return false;
12826
12827 CPSRWriteByInstr(spsr, 15, true);
12828
12829 // BranchWritePC(result);
12830 EmulateInstruction::Context context;
12831 context.type = eContextAdjustPC;
12832 context.SetImmediate(result.result);
12833
12834 BranchWritePC(context, result.result);
12835 }
12836 return true;
12837 }
12838
12839 EmulateInstructionARM::ARMOpcode *
GetARMOpcodeForInstruction(const uint32_t opcode,uint32_t arm_isa)12840 EmulateInstructionARM::GetARMOpcodeForInstruction(const uint32_t opcode,
12841 uint32_t arm_isa) {
12842 static ARMOpcode g_arm_opcodes[] = {
12843 // Prologue instructions
12844
12845 // push register(s)
12846 {0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12847 &EmulateInstructionARM::EmulatePUSH, "push <registers>"},
12848 {0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32,
12849 &EmulateInstructionARM::EmulatePUSH, "push <register>"},
12850
12851 // set r7 to point to a stack offset
12852 {0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12853 &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>"},
12854 {0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12855 &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
12856 // copy the stack pointer to ip
12857 {0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32,
12858 &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp"},
12859 {0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12860 &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>"},
12861 {0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12862 &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
12863
12864 // adjust the stack pointer
12865 {0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12866 &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
12867 {0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12868 &EmulateInstructionARM::EmulateSUBSPReg,
12869 "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},
12870
12871 // push one register
12872 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
12873 {0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12874 &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!"},
12875
12876 // vector push consecutive extension register(s)
12877 {0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32,
12878 &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12879 {0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,
12880 &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
12881
12882 // Epilogue instructions
12883
12884 {0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12885 &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12886 {0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32,
12887 &EmulateInstructionARM::EmulatePOP, "pop <register>"},
12888 {0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32,
12889 &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12890 {0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,
12891 &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
12892
12893 // Supervisor Call (previously Software Interrupt)
12894 {0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12895 &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
12896
12897 // Branch instructions
12898 // To resolve ambiguity, "blx <label>" should come before "b #imm24" and
12899 // "bl <label>".
12900 {0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32,
12901 &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12902 {0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12903 &EmulateInstructionARM::EmulateB, "b #imm24"},
12904 {0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12905 &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
12906 {0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32,
12907 &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
12908 // for example, "bx lr"
12909 {0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32,
12910 &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
12911 // bxj
12912 {0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32,
12913 &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
12914
12915 // Data-processing instructions
12916 // adc (immediate)
12917 {0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12918 &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
12919 // adc (register)
12920 {0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12921 &EmulateInstructionARM::EmulateADCReg,
12922 "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12923 // add (immediate)
12924 {0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12925 &EmulateInstructionARM::EmulateADDImmARM,
12926 "add{s}<c> <Rd>, <Rn>, #const"},
12927 // add (register)
12928 {0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12929 &EmulateInstructionARM::EmulateADDReg,
12930 "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12931 // add (register-shifted register)
12932 {0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32,
12933 &EmulateInstructionARM::EmulateADDRegShift,
12934 "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
12935 // adr
12936 {0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12937 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12938 {0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32,
12939 &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
12940 // and (immediate)
12941 {0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12942 &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
12943 // and (register)
12944 {0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12945 &EmulateInstructionARM::EmulateANDReg,
12946 "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12947 // bic (immediate)
12948 {0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12949 &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
12950 // bic (register)
12951 {0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12952 &EmulateInstructionARM::EmulateBICReg,
12953 "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12954 // eor (immediate)
12955 {0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12956 &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
12957 // eor (register)
12958 {0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12959 &EmulateInstructionARM::EmulateEORReg,
12960 "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12961 // orr (immediate)
12962 {0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12963 &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
12964 // orr (register)
12965 {0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12966 &EmulateInstructionARM::EmulateORRReg,
12967 "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12968 // rsb (immediate)
12969 {0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12970 &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
12971 // rsb (register)
12972 {0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12973 &EmulateInstructionARM::EmulateRSBReg,
12974 "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12975 // rsc (immediate)
12976 {0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12977 &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
12978 // rsc (register)
12979 {0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12980 &EmulateInstructionARM::EmulateRSCReg,
12981 "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12982 // sbc (immediate)
12983 {0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12984 &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
12985 // sbc (register)
12986 {0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12987 &EmulateInstructionARM::EmulateSBCReg,
12988 "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12989 // sub (immediate, ARM)
12990 {0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12991 &EmulateInstructionARM::EmulateSUBImmARM,
12992 "sub{s}<c> <Rd>, <Rn>, #<const>"},
12993 // sub (sp minus immediate)
12994 {0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12995 &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
12996 // sub (register)
12997 {0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12998 &EmulateInstructionARM::EmulateSUBReg,
12999 "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
13000 // teq (immediate)
13001 {0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13002 &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
13003 // teq (register)
13004 {0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13005 &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
13006 // tst (immediate)
13007 {0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13008 &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
13009 // tst (register)
13010 {0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13011 &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
13012
13013 // mov (immediate)
13014 {0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13015 &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
13016 {0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,
13017 &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>"},
13018 // mov (register)
13019 {0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13020 &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
13021 // mvn (immediate)
13022 {0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13023 &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
13024 // mvn (register)
13025 {0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13026 &EmulateInstructionARM::EmulateMVNReg,
13027 "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
13028 // cmn (immediate)
13029 {0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13030 &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
13031 // cmn (register)
13032 {0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13033 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
13034 // cmp (immediate)
13035 {0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13036 &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
13037 // cmp (register)
13038 {0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13039 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
13040 // asr (immediate)
13041 {0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32,
13042 &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
13043 // asr (register)
13044 {0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32,
13045 &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
13046 // lsl (immediate)
13047 {0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13048 &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
13049 // lsl (register)
13050 {0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32,
13051 &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
13052 // lsr (immediate)
13053 {0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32,
13054 &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
13055 // lsr (register)
13056 {0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32,
13057 &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
13058 // rrx is a special case encoding of ror (immediate)
13059 {0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32,
13060 &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
13061 // ror (immediate)
13062 {0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32,
13063 &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
13064 // ror (register)
13065 {0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32,
13066 &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
13067 // mul
13068 {0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32,
13069 &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>"},
13070
13071 // subs pc, lr and related instructions
13072 {0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13073 &EmulateInstructionARM::EmulateSUBSPcLrEtc,
13074 "<opc>S<c> PC,#<const> | <Rn>,#<const>"},
13075 {0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32,
13076 &EmulateInstructionARM::EmulateSUBSPcLrEtc,
13077 "<opc>S<c> PC,<Rn>,<Rm{,<shift>}"},
13078
13079 // Load instructions
13080 {0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13081 &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"},
13082 {0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13083 &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>"},
13084 {0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13085 &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"},
13086 {0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13087 &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>"},
13088 {0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13089 &EmulateInstructionARM::EmulateLDRImmediateARM,
13090 "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]"},
13091 {0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13092 &EmulateInstructionARM::EmulateLDRRegister,
13093 "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}"},
13094 {0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13095 &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
13096 {0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13097 &EmulateInstructionARM::EmulateLDRBRegister,
13098 "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}"},
13099 {0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13100 &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"},
13101 {0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13102 &EmulateInstructionARM::EmulateLDRHRegister,
13103 "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13104 {0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13105 &EmulateInstructionARM::EmulateLDRSBImmediate,
13106 "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]"},
13107 {0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13108 &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>"},
13109 {0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13110 &EmulateInstructionARM::EmulateLDRSBRegister,
13111 "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13112 {0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13113 &EmulateInstructionARM::EmulateLDRSHImmediate,
13114 "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
13115 {0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13116 &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"},
13117 {0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13118 &EmulateInstructionARM::EmulateLDRSHRegister,
13119 "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13120 {0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13121 &EmulateInstructionARM::EmulateLDRDImmediate,
13122 "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
13123 {0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13124 &EmulateInstructionARM::EmulateLDRDRegister,
13125 "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
13126 {0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13127 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13128 {0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13129 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13130 {0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13131 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13132 {0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13133 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
13134 {0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13135 &EmulateInstructionARM::EmulateVLD1Multiple,
13136 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13137 {0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13138 &EmulateInstructionARM::EmulateVLD1Single,
13139 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13140 {0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13141 &EmulateInstructionARM::EmulateVLD1SingleAll,
13142 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13143
13144 // Store instructions
13145 {0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13146 &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"},
13147 {0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13148 &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>"},
13149 {0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13150 &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"},
13151 {0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13152 &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>"},
13153 {0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13154 &EmulateInstructionARM::EmulateSTRRegister,
13155 "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}"},
13156 {0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13157 &EmulateInstructionARM::EmulateSTRHRegister,
13158 "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}"},
13159 {0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13160 &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
13161 {0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13162 &EmulateInstructionARM::EmulateSTRBImmARM,
13163 "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
13164 {0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13165 &EmulateInstructionARM::EmulateSTRImmARM,
13166 "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
13167 {0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13168 &EmulateInstructionARM::EmulateSTRDImm,
13169 "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
13170 {0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13171 &EmulateInstructionARM::EmulateSTRDReg,
13172 "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
13173 {0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13174 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
13175 {0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13176 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
13177 {0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13178 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
13179 {0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13180 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
13181 {0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13182 &EmulateInstructionARM::EmulateVST1Multiple,
13183 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13184 {0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13185 &EmulateInstructionARM::EmulateVST1Single,
13186 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13187
13188 // Other instructions
13189 {0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13190 &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}"},
13191 {0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13192 &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}"},
13193 {0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13194 &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}"},
13195 {0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13196 &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}"},
13197 {0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13198 &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}"}
13199
13200 };
13201 static const size_t k_num_arm_opcodes = llvm::array_lengthof(g_arm_opcodes);
13202
13203 for (size_t i = 0; i < k_num_arm_opcodes; ++i) {
13204 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value &&
13205 (g_arm_opcodes[i].variants & arm_isa) != 0)
13206 return &g_arm_opcodes[i];
13207 }
13208 return nullptr;
13209 }
13210
13211 EmulateInstructionARM::ARMOpcode *
GetThumbOpcodeForInstruction(const uint32_t opcode,uint32_t arm_isa)13212 EmulateInstructionARM::GetThumbOpcodeForInstruction(const uint32_t opcode,
13213 uint32_t arm_isa) {
13214
13215 static ARMOpcode g_thumb_opcodes[] = {
13216 // Prologue instructions
13217
13218 // push register(s)
13219 {0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16,
13220 &EmulateInstructionARM::EmulatePUSH, "push <registers>"},
13221 {0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13222 &EmulateInstructionARM::EmulatePUSH, "push.w <registers>"},
13223 {0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13224 &EmulateInstructionARM::EmulatePUSH, "push.w <register>"},
13225
13226 // set r7 to point to a stack offset
13227 {0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13228 &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm"},
13229 // copy the stack pointer to r7
13230 {0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16,
13231 &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp"},
13232 // move from high register to low register (comes after "mov r7, sp" to
13233 // resolve ambiguity)
13234 {0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16,
13235 &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15"},
13236
13237 // PC-relative load into register (see also EmulateADDSPRm)
13238 {0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13239 &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
13240
13241 // adjust the stack pointer
13242 {0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16,
13243 &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
13244 {0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16,
13245 &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
13246 {0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13247 &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
13248 {0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13249 &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
13250 {0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13251 &EmulateInstructionARM::EmulateSUBSPReg,
13252 "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},
13253
13254 // vector push consecutive extension register(s)
13255 {0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13256 &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
13257 {0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13258 &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
13259
13260 // Epilogue instructions
13261
13262 {0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13263 &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
13264 {0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16,
13265 &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
13266 {0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13267 &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
13268 {0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13269 &EmulateInstructionARM::EmulatePOP, "pop.w <registers>"},
13270 {0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13271 &EmulateInstructionARM::EmulatePOP, "pop.w <register>"},
13272 {0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13273 &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
13274 {0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13275 &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
13276
13277 // Supervisor Call (previously Software Interrupt)
13278 {0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13279 &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
13280
13281 // If Then makes up to four following instructions conditional.
13282 // The next 5 opcode _must_ come before the if then instruction
13283 {0xffffffff, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13284 &EmulateInstructionARM::EmulateNop, "nop"},
13285 {0xffffffff, 0x0000bf10, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13286 &EmulateInstructionARM::EmulateNop, "nop YIELD (yield hint)"},
13287 {0xffffffff, 0x0000bf20, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13288 &EmulateInstructionARM::EmulateNop, "nop WFE (wait for event hint)"},
13289 {0xffffffff, 0x0000bf30, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13290 &EmulateInstructionARM::EmulateNop, "nop WFI (wait for interrupt hint)"},
13291 {0xffffffff, 0x0000bf40, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13292 &EmulateInstructionARM::EmulateNop, "nop SEV (send event hint)"},
13293 {0xffffff00, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13294 &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
13295
13296 // Branch instructions
13297 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
13298 {0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13299 &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
13300 {0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16,
13301 &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
13302 {0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13303 &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
13304 {0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13305 &EmulateInstructionARM::EmulateB,
13306 "b<c>.w #imm8 (outside or last in IT)"},
13307 // J1 == J2 == 1
13308 {0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32,
13309 &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
13310 // J1 == J2 == 1
13311 {0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32,
13312 &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
13313 {0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16,
13314 &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
13315 // for example, "bx lr"
13316 {0xffffff87, 0x00004700, ARMvAll, eEncodingT1, No_VFP, eSize32,
13317 &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
13318 // bxj
13319 {0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32,
13320 &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
13321 // compare and branch
13322 {0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13323 &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
13324 // table branch byte
13325 {0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13326 &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
13327 // table branch halfword
13328 {0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13329 &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
13330
13331 // Data-processing instructions
13332 // adc (immediate)
13333 {0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13334 &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
13335 // adc (register)
13336 {0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16,
13337 &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
13338 {0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13339 &EmulateInstructionARM::EmulateADCReg,
13340 "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13341 // add (register)
13342 {0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13343 &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
13344 // Make sure "add sp, <Rm>" comes before this instruction, so there's no
13345 // ambiguity decoding the two.
13346 {0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16,
13347 &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
13348 // adr
13349 {0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13350 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
13351 {0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13352 &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
13353 {0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13354 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
13355 // and (immediate)
13356 {0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13357 &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
13358 // and (register)
13359 {0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13360 &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
13361 {0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13362 &EmulateInstructionARM::EmulateANDReg,
13363 "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13364 // bic (immediate)
13365 {0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13366 &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
13367 // bic (register)
13368 {0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16,
13369 &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
13370 {0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13371 &EmulateInstructionARM::EmulateBICReg,
13372 "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13373 // eor (immediate)
13374 {0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13375 &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
13376 // eor (register)
13377 {0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16,
13378 &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
13379 {0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13380 &EmulateInstructionARM::EmulateEORReg,
13381 "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13382 // orr (immediate)
13383 {0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13384 &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
13385 // orr (register)
13386 {0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16,
13387 &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
13388 {0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13389 &EmulateInstructionARM::EmulateORRReg,
13390 "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13391 // rsb (immediate)
13392 {0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16,
13393 &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
13394 {0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13395 &EmulateInstructionARM::EmulateRSBImm,
13396 "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
13397 // rsb (register)
13398 {0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13399 &EmulateInstructionARM::EmulateRSBReg,
13400 "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13401 // sbc (immediate)
13402 {0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13403 &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
13404 // sbc (register)
13405 {0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16,
13406 &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
13407 {0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13408 &EmulateInstructionARM::EmulateSBCReg,
13409 "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13410 // add (immediate, Thumb)
13411 {0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13412 &EmulateInstructionARM::EmulateADDImmThumb,
13413 "adds|add<c> <Rd>,<Rn>,#<imm3>"},
13414 {0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,
13415 &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>"},
13416 {0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13417 &EmulateInstructionARM::EmulateADDImmThumb,
13418 "add{s}<c>.w <Rd>,<Rn>,#<const>"},
13419 {0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13420 &EmulateInstructionARM::EmulateADDImmThumb,
13421 "addw<c> <Rd>,<Rn>,#<imm12>"},
13422 // sub (immediate, Thumb)
13423 {0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13424 &EmulateInstructionARM::EmulateSUBImmThumb,
13425 "subs|sub<c> <Rd>, <Rn> #imm3"},
13426 {0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16,
13427 &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
13428 {0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13429 &EmulateInstructionARM::EmulateSUBImmThumb,
13430 "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
13431 {0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13432 &EmulateInstructionARM::EmulateSUBImmThumb,
13433 "subw<c> <Rd>, <Rn>, #imm12"},
13434 // sub (sp minus immediate)
13435 {0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13436 &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
13437 {0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13438 &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
13439 // sub (register)
13440 {0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13441 &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
13442 {0xffe08000, 0xeba00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13443 &EmulateInstructionARM::EmulateSUBReg,
13444 "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"},
13445 // teq (immediate)
13446 {0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13447 &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
13448 // teq (register)
13449 {0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13450 &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
13451 // tst (immediate)
13452 {0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13453 &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
13454 // tst (register)
13455 {0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16,
13456 &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
13457 {0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13458 &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
13459
13460 // move from high register to high register
13461 {0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16,
13462 &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
13463 // move from low register to low register
13464 {0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16,
13465 &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
13466 // mov{s}<c>.w <Rd>, <Rm>
13467 {0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13468 &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
13469 // move immediate
13470 {0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13471 &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
13472 {0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13473 &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
13474 {0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13475 &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
13476 // mvn (immediate)
13477 {0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13478 &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
13479 // mvn (register)
13480 {0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13481 &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
13482 {0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13483 &EmulateInstructionARM::EmulateMVNReg,
13484 "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
13485 // cmn (immediate)
13486 {0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13487 &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
13488 // cmn (register)
13489 {0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13490 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
13491 {0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13492 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
13493 // cmp (immediate)
13494 {0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13495 &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
13496 {0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13497 &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
13498 // cmp (register) (Rn and Rm both from r0-r7)
13499 {0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16,
13500 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
13501 // cmp (register) (Rn and Rm not both from r0-r7)
13502 {0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16,
13503 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
13504 {0xfff08f00, 0xebb00f00, ARMvAll, eEncodingT3, No_VFP, eSize16,
13505 &EmulateInstructionARM::EmulateCMPReg,
13506 "cmp<c>.w <Rn>, <Rm> {, <shift>}"},
13507 // asr (immediate)
13508 {0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13509 &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
13510 {0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13511 &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
13512 // asr (register)
13513 {0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16,
13514 &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
13515 {0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13516 &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
13517 // lsl (immediate)
13518 {0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13519 &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
13520 {0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13521 &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
13522 // lsl (register)
13523 {0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16,
13524 &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
13525 {0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13526 &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
13527 // lsr (immediate)
13528 {0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13529 &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
13530 {0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13531 &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
13532 // lsr (register)
13533 {0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13534 &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
13535 {0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13536 &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
13537 // rrx is a special case encoding of ror (immediate)
13538 {0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13539 &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
13540 // ror (immediate)
13541 {0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13542 &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
13543 // ror (register)
13544 {0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13545 &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
13546 {0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13547 &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
13548 // mul
13549 {0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13550 &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>"},
13551 // mul
13552 {0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13553 &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>"},
13554
13555 // subs pc, lr and related instructions
13556 {0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13557 &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>"},
13558
13559 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE
13560 // LDM.. Instructions in this table;
13561 // otherwise the wrong instructions will be selected.
13562
13563 {0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13564 &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}"},
13565 {0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13566 &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}"},
13567
13568 // Load instructions
13569 {0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13570 &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"},
13571 {0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13572 &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>"},
13573 {0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13574 &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"},
13575 {0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13576 &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
13577 {0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,
13578 &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
13579 {0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13580 &EmulateInstructionARM::EmulateLDRRtRnImm,
13581 "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
13582 {0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13583 &EmulateInstructionARM::EmulateLDRRtRnImm,
13584 "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
13585 // Thumb2 PC-relative load into register
13586 {0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13587 &EmulateInstructionARM::EmulateLDRRtPCRelative,
13588 "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
13589 {0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13590 &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]"},
13591 {0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13592 &EmulateInstructionARM::EmulateLDRRegister,
13593 "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]"},
13594 {0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13595 &EmulateInstructionARM::EmulateLDRBImmediate,
13596 "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]"},
13597 {0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13598 &EmulateInstructionARM::EmulateLDRBImmediate,
13599 "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]"},
13600 {0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13601 &EmulateInstructionARM::EmulateLDRBImmediate,
13602 "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}"},
13603 {0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13604 &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]"},
13605 {0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13606 &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]"},
13607 {0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13608 &EmulateInstructionARM::EmulateLDRBRegister,
13609 "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},
13610 {0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13611 &EmulateInstructionARM::EmulateLDRHImmediate,
13612 "ldrh<c> <Rt>, [<Rn>{,#<imm>}]"},
13613 {0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13614 &EmulateInstructionARM::EmulateLDRHImmediate,
13615 "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]"},
13616 {0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13617 &EmulateInstructionARM::EmulateLDRHImmediate,
13618 "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}"},
13619 {0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13620 &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"},
13621 {0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13622 &EmulateInstructionARM::EmulateLDRHRegister,
13623 "ldrh<c> <Rt>, [<Rn>,<Rm>]"},
13624 {0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13625 &EmulateInstructionARM::EmulateLDRHRegister,
13626 "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13627 {0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13628 &EmulateInstructionARM::EmulateLDRSBImmediate,
13629 "ldrsb<c> <Rt>,[<Rn>,#<imm12>]"},
13630 {0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13631 &EmulateInstructionARM::EmulateLDRSBImmediate,
13632 "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]"},
13633 {0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13634 &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>"},
13635 {0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13636 &EmulateInstructionARM::EmulateLDRSBRegister,
13637 "ldrsb<c> <Rt>,[<Rn>,<Rm>]"},
13638 {0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13639 &EmulateInstructionARM::EmulateLDRSBRegister,
13640 "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},
13641 {0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13642 &EmulateInstructionARM::EmulateLDRSHImmediate,
13643 "ldrsh<c> <Rt>,[<Rn>,#<imm12>]"},
13644 {0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13645 &EmulateInstructionARM::EmulateLDRSHImmediate,
13646 "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]"},
13647 {0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13648 &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"},
13649 {0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13650 &EmulateInstructionARM::EmulateLDRSHRegister,
13651 "ldrsh<c> <Rt>,[<Rn>,<Rm>]"},
13652 {0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13653 &EmulateInstructionARM::EmulateLDRSHRegister,
13654 "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13655 {0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13656 &EmulateInstructionARM::EmulateLDRDImmediate,
13657 "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
13658 {0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13659 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13660 {0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13661 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13662 {0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13663 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13664 {0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13665 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
13666 {0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13667 &EmulateInstructionARM::EmulateVLD1Multiple,
13668 "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
13669 {0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13670 &EmulateInstructionARM::EmulateVLD1Single,
13671 "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
13672 {0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13673 &EmulateInstructionARM::EmulateVLD1SingleAll,
13674 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13675
13676 // Store instructions
13677 {0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13678 &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"},
13679 {0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13680 &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>"},
13681 {0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13682 &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"},
13683 {0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13684 &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]"},
13685 {0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,
13686 &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]"},
13687 {0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13688 &EmulateInstructionARM::EmulateSTRThumb,
13689 "str<c>.w <Rt>, [<Rn>,#<imm12>]"},
13690 {0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13691 &EmulateInstructionARM::EmulateSTRThumb,
13692 "str<c> <Rt>, [<Rn>,#+/-<imm8>]"},
13693 {0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13694 &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]"},
13695 {0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13696 &EmulateInstructionARM::EmulateSTRRegister,
13697 "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]"},
13698 {0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13699 &EmulateInstructionARM::EmulateSTRBThumb,
13700 "strb<c> <Rt>, [<Rn>, #<imm5>]"},
13701 {0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13702 &EmulateInstructionARM::EmulateSTRBThumb,
13703 "strb<c>.w <Rt>, [<Rn>, #<imm12>]"},
13704 {0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13705 &EmulateInstructionARM::EmulateSTRBThumb,
13706 "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}"},
13707 {0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13708 &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]"},
13709 {0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13710 &EmulateInstructionARM::EmulateSTRHRegister,
13711 "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13712 {0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13713 &EmulateInstructionARM::EmulateSTREX,
13714 "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]"},
13715 {0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13716 &EmulateInstructionARM::EmulateSTRDImm,
13717 "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
13718 {0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13719 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
13720 {0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13721 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
13722 {0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13723 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13724 {0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13725 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
13726 {0xffb00000, 0xf9000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13727 &EmulateInstructionARM::EmulateVST1Multiple,
13728 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13729 {0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13730 &EmulateInstructionARM::EmulateVST1Single,
13731 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13732
13733 // Other instructions
13734 {0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13735 &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>"},
13736 {0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32,
13737 &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}"},
13738 {0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13739 &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>"},
13740 {0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13741 &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}"},
13742 {0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13743 &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>"},
13744 {0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13745 &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}"},
13746 {0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13747 &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>"},
13748 {0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13749 &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}"},
13750 };
13751
13752 const size_t k_num_thumb_opcodes = llvm::array_lengthof(g_thumb_opcodes);
13753 for (size_t i = 0; i < k_num_thumb_opcodes; ++i) {
13754 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value &&
13755 (g_thumb_opcodes[i].variants & arm_isa) != 0)
13756 return &g_thumb_opcodes[i];
13757 }
13758 return nullptr;
13759 }
13760
SetArchitecture(const ArchSpec & arch)13761 bool EmulateInstructionARM::SetArchitecture(const ArchSpec &arch) {
13762 m_arch = arch;
13763 m_arm_isa = 0;
13764 llvm::StringRef arch_cstr = arch.GetArchitectureName();
13765 if (arch_cstr.equals_insensitive("armv4t"))
13766 m_arm_isa = ARMv4T;
13767 else if (arch_cstr.equals_insensitive("armv5tej"))
13768 m_arm_isa = ARMv5TEJ;
13769 else if (arch_cstr.equals_insensitive("armv5te"))
13770 m_arm_isa = ARMv5TE;
13771 else if (arch_cstr.equals_insensitive("armv5t"))
13772 m_arm_isa = ARMv5T;
13773 else if (arch_cstr.equals_insensitive("armv6k"))
13774 m_arm_isa = ARMv6K;
13775 else if (arch_cstr.equals_insensitive("armv6t2"))
13776 m_arm_isa = ARMv6T2;
13777 else if (arch_cstr.equals_insensitive("armv7s"))
13778 m_arm_isa = ARMv7S;
13779 else if (arch_cstr.equals_insensitive("arm"))
13780 m_arm_isa = ARMvAll;
13781 else if (arch_cstr.equals_insensitive("thumb"))
13782 m_arm_isa = ARMvAll;
13783 else if (arch_cstr.startswith_insensitive("armv4"))
13784 m_arm_isa = ARMv4;
13785 else if (arch_cstr.startswith_insensitive("armv6"))
13786 m_arm_isa = ARMv6;
13787 else if (arch_cstr.startswith_insensitive("armv7"))
13788 m_arm_isa = ARMv7;
13789 else if (arch_cstr.startswith_insensitive("armv8"))
13790 m_arm_isa = ARMv8;
13791 return m_arm_isa != 0;
13792 }
13793
SetInstruction(const Opcode & insn_opcode,const Address & inst_addr,Target * target)13794 bool EmulateInstructionARM::SetInstruction(const Opcode &insn_opcode,
13795 const Address &inst_addr,
13796 Target *target) {
13797 if (EmulateInstruction::SetInstruction(insn_opcode, inst_addr, target)) {
13798 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb ||
13799 m_arch.IsAlwaysThumbInstructions())
13800 m_opcode_mode = eModeThumb;
13801 else {
13802 AddressClass addr_class = inst_addr.GetAddressClass();
13803
13804 if ((addr_class == AddressClass::eCode) ||
13805 (addr_class == AddressClass::eUnknown))
13806 m_opcode_mode = eModeARM;
13807 else if (addr_class == AddressClass::eCodeAlternateISA)
13808 m_opcode_mode = eModeThumb;
13809 else
13810 return false;
13811 }
13812 if (m_opcode_mode == eModeThumb || m_arch.IsAlwaysThumbInstructions())
13813 m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T;
13814 else
13815 m_opcode_cpsr = CPSR_MODE_USR;
13816 return true;
13817 }
13818 return false;
13819 }
13820
ReadInstruction()13821 bool EmulateInstructionARM::ReadInstruction() {
13822 bool success = false;
13823 m_opcode_cpsr = ReadRegisterUnsigned(eRegisterKindGeneric,
13824 LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
13825 if (success) {
13826 addr_t pc =
13827 ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
13828 LLDB_INVALID_ADDRESS, &success);
13829 if (success) {
13830 Context read_inst_context;
13831 read_inst_context.type = eContextReadOpcode;
13832 read_inst_context.SetNoArgs();
13833
13834 if ((m_opcode_cpsr & MASK_CPSR_T) || m_arch.IsAlwaysThumbInstructions()) {
13835 m_opcode_mode = eModeThumb;
13836 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
13837
13838 if (success) {
13839 if ((thumb_opcode & 0xe000) != 0xe000 ||
13840 ((thumb_opcode & 0x1800u) == 0)) {
13841 m_opcode.SetOpcode16(thumb_opcode, GetByteOrder());
13842 } else {
13843 m_opcode.SetOpcode32(
13844 (thumb_opcode << 16) |
13845 MemARead(read_inst_context, pc + 2, 2, 0, &success),
13846 GetByteOrder());
13847 }
13848 }
13849 } else {
13850 m_opcode_mode = eModeARM;
13851 m_opcode.SetOpcode32(MemARead(read_inst_context, pc, 4, 0, &success),
13852 GetByteOrder());
13853 }
13854
13855 if (!m_ignore_conditions) {
13856 // If we are not ignoreing the conditions then init the it session from
13857 // the current value of cpsr.
13858 uint32_t it = (Bits32(m_opcode_cpsr, 15, 10) << 2) |
13859 Bits32(m_opcode_cpsr, 26, 25);
13860 if (it != 0)
13861 m_it_session.InitIT(it);
13862 }
13863 }
13864 }
13865 if (!success) {
13866 m_opcode_mode = eModeInvalid;
13867 m_addr = LLDB_INVALID_ADDRESS;
13868 }
13869 return success;
13870 }
13871
ArchVersion()13872 uint32_t EmulateInstructionARM::ArchVersion() { return m_arm_isa; }
13873
ConditionPassed(const uint32_t opcode)13874 bool EmulateInstructionARM::ConditionPassed(const uint32_t opcode) {
13875 // If we are ignoring conditions, then always return true. this allows us to
13876 // iterate over disassembly code and still emulate an instruction even if we
13877 // don't have all the right bits set in the CPSR register...
13878 if (m_ignore_conditions)
13879 return true;
13880
13881 const uint32_t cond = CurrentCond(opcode);
13882 if (cond == UINT32_MAX)
13883 return false;
13884
13885 bool result = false;
13886 switch (UnsignedBits(cond, 3, 1)) {
13887 case 0:
13888 if (m_opcode_cpsr == 0)
13889 result = true;
13890 else
13891 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;
13892 break;
13893 case 1:
13894 if (m_opcode_cpsr == 0)
13895 result = true;
13896 else
13897 result = (m_opcode_cpsr & MASK_CPSR_C) != 0;
13898 break;
13899 case 2:
13900 if (m_opcode_cpsr == 0)
13901 result = true;
13902 else
13903 result = (m_opcode_cpsr & MASK_CPSR_N) != 0;
13904 break;
13905 case 3:
13906 if (m_opcode_cpsr == 0)
13907 result = true;
13908 else
13909 result = (m_opcode_cpsr & MASK_CPSR_V) != 0;
13910 break;
13911 case 4:
13912 if (m_opcode_cpsr == 0)
13913 result = true;
13914 else
13915 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) &&
13916 ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
13917 break;
13918 case 5:
13919 if (m_opcode_cpsr == 0)
13920 result = true;
13921 else {
13922 bool n = (m_opcode_cpsr & MASK_CPSR_N);
13923 bool v = (m_opcode_cpsr & MASK_CPSR_V);
13924 result = n == v;
13925 }
13926 break;
13927 case 6:
13928 if (m_opcode_cpsr == 0)
13929 result = true;
13930 else {
13931 bool n = (m_opcode_cpsr & MASK_CPSR_N);
13932 bool v = (m_opcode_cpsr & MASK_CPSR_V);
13933 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
13934 }
13935 break;
13936 case 7:
13937 // Always execute (cond == 0b1110, or the special 0b1111 which gives
13938 // opcodes different meanings, but always means execution happens.
13939 return true;
13940 }
13941
13942 if (cond & 1)
13943 result = !result;
13944 return result;
13945 }
13946
CurrentCond(const uint32_t opcode)13947 uint32_t EmulateInstructionARM::CurrentCond(const uint32_t opcode) {
13948 switch (m_opcode_mode) {
13949 case eModeInvalid:
13950 break;
13951
13952 case eModeARM:
13953 return UnsignedBits(opcode, 31, 28);
13954
13955 case eModeThumb:
13956 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
13957 // 'cond' field of the encoding.
13958 {
13959 const uint32_t byte_size = m_opcode.GetByteSize();
13960 if (byte_size == 2) {
13961 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 8) != 0x0f)
13962 return Bits32(opcode, 11, 8);
13963 } else if (byte_size == 4) {
13964 if (Bits32(opcode, 31, 27) == 0x1e && Bits32(opcode, 15, 14) == 0x02 &&
13965 Bits32(opcode, 12, 12) == 0x00 && Bits32(opcode, 25, 22) <= 0x0d) {
13966 return Bits32(opcode, 25, 22);
13967 }
13968 } else
13969 // We have an invalid thumb instruction, let's bail out.
13970 break;
13971
13972 return m_it_session.GetCond();
13973 }
13974 }
13975 return UINT32_MAX; // Return invalid value
13976 }
13977
InITBlock()13978 bool EmulateInstructionARM::InITBlock() {
13979 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
13980 }
13981
LastInITBlock()13982 bool EmulateInstructionARM::LastInITBlock() {
13983 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
13984 }
13985
BadMode(uint32_t mode)13986 bool EmulateInstructionARM::BadMode(uint32_t mode) {
13987
13988 switch (mode) {
13989 case 16:
13990 return false; // '10000'
13991 case 17:
13992 return false; // '10001'
13993 case 18:
13994 return false; // '10010'
13995 case 19:
13996 return false; // '10011'
13997 case 22:
13998 return false; // '10110'
13999 case 23:
14000 return false; // '10111'
14001 case 27:
14002 return false; // '11011'
14003 case 31:
14004 return false; // '11111'
14005 default:
14006 return true;
14007 }
14008 return true;
14009 }
14010
CurrentModeIsPrivileged()14011 bool EmulateInstructionARM::CurrentModeIsPrivileged() {
14012 uint32_t mode = Bits32(m_opcode_cpsr, 4, 0);
14013
14014 if (BadMode(mode))
14015 return false;
14016
14017 if (mode == 16)
14018 return false;
14019
14020 return true;
14021 }
14022
CPSRWriteByInstr(uint32_t value,uint32_t bytemask,bool affect_execstate)14023 void EmulateInstructionARM::CPSRWriteByInstr(uint32_t value, uint32_t bytemask,
14024 bool affect_execstate) {
14025 bool privileged = CurrentModeIsPrivileged();
14026
14027 uint32_t tmp_cpsr = Bits32(m_opcode_cpsr, 23, 20) << 20;
14028
14029 if (BitIsSet(bytemask, 3)) {
14030 tmp_cpsr = tmp_cpsr | (Bits32(value, 31, 27) << 27);
14031 if (affect_execstate)
14032 tmp_cpsr = tmp_cpsr | (Bits32(value, 26, 24) << 24);
14033 }
14034
14035 if (BitIsSet(bytemask, 2)) {
14036 tmp_cpsr = tmp_cpsr | (Bits32(value, 19, 16) << 16);
14037 }
14038
14039 if (BitIsSet(bytemask, 1)) {
14040 if (affect_execstate)
14041 tmp_cpsr = tmp_cpsr | (Bits32(value, 15, 10) << 10);
14042 tmp_cpsr = tmp_cpsr | (Bit32(value, 9) << 9);
14043 if (privileged)
14044 tmp_cpsr = tmp_cpsr | (Bit32(value, 8) << 8);
14045 }
14046
14047 if (BitIsSet(bytemask, 0)) {
14048 if (privileged)
14049 tmp_cpsr = tmp_cpsr | (Bits32(value, 7, 6) << 6);
14050 if (affect_execstate)
14051 tmp_cpsr = tmp_cpsr | (Bit32(value, 5) << 5);
14052 if (privileged)
14053 tmp_cpsr = tmp_cpsr | Bits32(value, 4, 0);
14054 }
14055
14056 m_opcode_cpsr = tmp_cpsr;
14057 }
14058
BranchWritePC(const Context & context,uint32_t addr)14059 bool EmulateInstructionARM::BranchWritePC(const Context &context,
14060 uint32_t addr) {
14061 addr_t target;
14062
14063 // Check the current instruction set.
14064 if (CurrentInstrSet() == eModeARM)
14065 target = addr & 0xfffffffc;
14066 else
14067 target = addr & 0xfffffffe;
14068
14069 return WriteRegisterUnsigned(context, eRegisterKindGeneric,
14070 LLDB_REGNUM_GENERIC_PC, target);
14071 }
14072
14073 // As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by
14074 // inspecting addr.
BXWritePC(Context & context,uint32_t addr)14075 bool EmulateInstructionARM::BXWritePC(Context &context, uint32_t addr) {
14076 addr_t target;
14077 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
14078 // we want to record it and issue a WriteRegister callback so the clients can
14079 // track the mode changes accordingly.
14080 bool cpsr_changed = false;
14081
14082 if (BitIsSet(addr, 0)) {
14083 if (CurrentInstrSet() != eModeThumb) {
14084 SelectInstrSet(eModeThumb);
14085 cpsr_changed = true;
14086 }
14087 target = addr & 0xfffffffe;
14088 context.SetISA(eModeThumb);
14089 } else if (BitIsClear(addr, 1)) {
14090 if (CurrentInstrSet() != eModeARM) {
14091 SelectInstrSet(eModeARM);
14092 cpsr_changed = true;
14093 }
14094 target = addr & 0xfffffffc;
14095 context.SetISA(eModeARM);
14096 } else
14097 return false; // address<1:0> == '10' => UNPREDICTABLE
14098
14099 if (cpsr_changed) {
14100 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
14101 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
14102 return false;
14103 }
14104 return WriteRegisterUnsigned(context, eRegisterKindGeneric,
14105 LLDB_REGNUM_GENERIC_PC, target);
14106 }
14107
14108 // Dispatches to either BXWritePC or BranchWritePC based on architecture
14109 // versions.
LoadWritePC(Context & context,uint32_t addr)14110 bool EmulateInstructionARM::LoadWritePC(Context &context, uint32_t addr) {
14111 if (ArchVersion() >= ARMv5T)
14112 return BXWritePC(context, addr);
14113 else
14114 return BranchWritePC((const Context)context, addr);
14115 }
14116
14117 // Dispatches to either BXWritePC or BranchWritePC based on architecture
14118 // versions and current instruction set.
ALUWritePC(Context & context,uint32_t addr)14119 bool EmulateInstructionARM::ALUWritePC(Context &context, uint32_t addr) {
14120 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
14121 return BXWritePC(context, addr);
14122 else
14123 return BranchWritePC((const Context)context, addr);
14124 }
14125
CurrentInstrSet()14126 EmulateInstructionARM::Mode EmulateInstructionARM::CurrentInstrSet() {
14127 return m_opcode_mode;
14128 }
14129
14130 // Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
14131 // ReadInstruction() is performed. This function has a side effect of updating
14132 // the m_new_inst_cpsr member variable if necessary.
SelectInstrSet(Mode arm_or_thumb)14133 bool EmulateInstructionARM::SelectInstrSet(Mode arm_or_thumb) {
14134 m_new_inst_cpsr = m_opcode_cpsr;
14135 switch (arm_or_thumb) {
14136 default:
14137 return false;
14138 case eModeARM:
14139 // Clear the T bit.
14140 m_new_inst_cpsr &= ~MASK_CPSR_T;
14141 break;
14142 case eModeThumb:
14143 // Set the T bit.
14144 m_new_inst_cpsr |= MASK_CPSR_T;
14145 break;
14146 }
14147 return true;
14148 }
14149
14150 // This function returns TRUE if the processor currently provides support for
14151 // unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
14152 // controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
UnalignedSupport()14153 bool EmulateInstructionARM::UnalignedSupport() {
14154 return (ArchVersion() >= ARMv7);
14155 }
14156
14157 // The main addition and subtraction instructions can produce status
14158 // information about both unsigned carry and signed overflow conditions. This
14159 // status information can be used to synthesize multi-word additions and
14160 // subtractions.
14161 EmulateInstructionARM::AddWithCarryResult
AddWithCarry(uint32_t x,uint32_t y,uint8_t carry_in)14162 EmulateInstructionARM::AddWithCarry(uint32_t x, uint32_t y, uint8_t carry_in) {
14163 uint32_t result;
14164 uint8_t carry_out;
14165 uint8_t overflow;
14166
14167 uint64_t unsigned_sum = x + y + carry_in;
14168 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
14169
14170 result = UnsignedBits(unsigned_sum, 31, 0);
14171 // carry_out = (result == unsigned_sum ? 0 : 1);
14172 overflow = ((int32_t)result == signed_sum ? 0 : 1);
14173
14174 if (carry_in)
14175 carry_out = ((int32_t)x >= (int32_t)(~y)) ? 1 : 0;
14176 else
14177 carry_out = ((int32_t)x > (int32_t)y) ? 1 : 0;
14178
14179 AddWithCarryResult res = {result, carry_out, overflow};
14180 return res;
14181 }
14182
ReadCoreReg(uint32_t num,bool * success)14183 uint32_t EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success) {
14184 lldb::RegisterKind reg_kind;
14185 uint32_t reg_num;
14186 switch (num) {
14187 case SP_REG:
14188 reg_kind = eRegisterKindGeneric;
14189 reg_num = LLDB_REGNUM_GENERIC_SP;
14190 break;
14191 case LR_REG:
14192 reg_kind = eRegisterKindGeneric;
14193 reg_num = LLDB_REGNUM_GENERIC_RA;
14194 break;
14195 case PC_REG:
14196 reg_kind = eRegisterKindGeneric;
14197 reg_num = LLDB_REGNUM_GENERIC_PC;
14198 break;
14199 default:
14200 if (num < SP_REG) {
14201 reg_kind = eRegisterKindDWARF;
14202 reg_num = dwarf_r0 + num;
14203 } else {
14204 // assert(0 && "Invalid register number");
14205 *success = false;
14206 return UINT32_MAX;
14207 }
14208 break;
14209 }
14210
14211 // Read our register.
14212 uint32_t val = ReadRegisterUnsigned(reg_kind, reg_num, 0, success);
14213
14214 // When executing an ARM instruction , PC reads as the address of the current
14215 // instruction plus 8. When executing a Thumb instruction , PC reads as the
14216 // address of the current instruction plus 4.
14217 if (num == 15) {
14218 if (CurrentInstrSet() == eModeARM)
14219 val += 8;
14220 else
14221 val += 4;
14222 }
14223
14224 return val;
14225 }
14226
14227 // Write the result to the ARM core register Rd, and optionally update the
14228 // condition flags based on the result.
14229 //
14230 // This helper method tries to encapsulate the following pseudocode from the
14231 // ARM Architecture Reference Manual:
14232 //
14233 // if d == 15 then // Can only occur for encoding A1
14234 // ALUWritePC(result); // setflags is always FALSE here
14235 // else
14236 // R[d] = result;
14237 // if setflags then
14238 // APSR.N = result<31>;
14239 // APSR.Z = IsZeroBit(result);
14240 // APSR.C = carry;
14241 // // APSR.V unchanged
14242 //
14243 // In the above case, the API client does not pass in the overflow arg, which
14244 // defaults to ~0u.
WriteCoreRegOptionalFlags(Context & context,const uint32_t result,const uint32_t Rd,bool setflags,const uint32_t carry,const uint32_t overflow)14245 bool EmulateInstructionARM::WriteCoreRegOptionalFlags(
14246 Context &context, const uint32_t result, const uint32_t Rd, bool setflags,
14247 const uint32_t carry, const uint32_t overflow) {
14248 if (Rd == 15) {
14249 if (!ALUWritePC(context, result))
14250 return false;
14251 } else {
14252 lldb::RegisterKind reg_kind;
14253 uint32_t reg_num;
14254 switch (Rd) {
14255 case SP_REG:
14256 reg_kind = eRegisterKindGeneric;
14257 reg_num = LLDB_REGNUM_GENERIC_SP;
14258 break;
14259 case LR_REG:
14260 reg_kind = eRegisterKindGeneric;
14261 reg_num = LLDB_REGNUM_GENERIC_RA;
14262 break;
14263 default:
14264 reg_kind = eRegisterKindDWARF;
14265 reg_num = dwarf_r0 + Rd;
14266 }
14267 if (!WriteRegisterUnsigned(context, reg_kind, reg_num, result))
14268 return false;
14269 if (setflags)
14270 return WriteFlags(context, result, carry, overflow);
14271 }
14272 return true;
14273 }
14274
14275 // This helper method tries to encapsulate the following pseudocode from the
14276 // ARM Architecture Reference Manual:
14277 //
14278 // APSR.N = result<31>;
14279 // APSR.Z = IsZeroBit(result);
14280 // APSR.C = carry;
14281 // APSR.V = overflow
14282 //
14283 // Default arguments can be specified for carry and overflow parameters, which
14284 // means not to update the respective flags.
WriteFlags(Context & context,const uint32_t result,const uint32_t carry,const uint32_t overflow)14285 bool EmulateInstructionARM::WriteFlags(Context &context, const uint32_t result,
14286 const uint32_t carry,
14287 const uint32_t overflow) {
14288 m_new_inst_cpsr = m_opcode_cpsr;
14289 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
14290 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
14291 if (carry != ~0u)
14292 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
14293 if (overflow != ~0u)
14294 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
14295 if (m_new_inst_cpsr != m_opcode_cpsr) {
14296 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
14297 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
14298 return false;
14299 }
14300 return true;
14301 }
14302
EvaluateInstruction(uint32_t evaluate_options)14303 bool EmulateInstructionARM::EvaluateInstruction(uint32_t evaluate_options) {
14304 ARMOpcode *opcode_data = nullptr;
14305
14306 if (m_opcode_mode == eModeThumb)
14307 opcode_data =
14308 GetThumbOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa);
14309 else if (m_opcode_mode == eModeARM)
14310 opcode_data = GetARMOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa);
14311
14312 const bool auto_advance_pc =
14313 evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
14314 m_ignore_conditions =
14315 evaluate_options & eEmulateInstructionOptionIgnoreConditions;
14316
14317 bool success = false;
14318 if (m_opcode_cpsr == 0 || !m_ignore_conditions) {
14319 m_opcode_cpsr =
14320 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success);
14321 }
14322
14323 // Only return false if we are unable to read the CPSR if we care about
14324 // conditions
14325 if (!success && !m_ignore_conditions)
14326 return false;
14327
14328 uint32_t orig_pc_value = 0;
14329 if (auto_advance_pc) {
14330 orig_pc_value =
14331 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success);
14332 if (!success)
14333 return false;
14334 }
14335
14336 // Call the Emulate... function if we managed to decode the opcode.
14337 if (opcode_data) {
14338 success = (this->*opcode_data->callback)(m_opcode.GetOpcode32(),
14339 opcode_data->encoding);
14340 if (!success)
14341 return false;
14342 }
14343
14344 // Advance the ITSTATE bits to their values for the next instruction if we
14345 // haven't just executed an IT instruction what initialized it.
14346 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock() &&
14347 (opcode_data == nullptr ||
14348 opcode_data->callback != &EmulateInstructionARM::EmulateIT))
14349 m_it_session.ITAdvance();
14350
14351 if (auto_advance_pc) {
14352 uint32_t after_pc_value =
14353 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success);
14354 if (!success)
14355 return false;
14356
14357 if (after_pc_value == orig_pc_value) {
14358 after_pc_value += m_opcode.GetByteSize();
14359
14360 EmulateInstruction::Context context;
14361 context.type = eContextAdvancePC;
14362 context.SetNoArgs();
14363 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc,
14364 after_pc_value))
14365 return false;
14366 }
14367 }
14368 return true;
14369 }
14370
14371 EmulateInstruction::InstructionCondition
GetInstructionCondition()14372 EmulateInstructionARM::GetInstructionCondition() {
14373 const uint32_t cond = CurrentCond(m_opcode.GetOpcode32());
14374 if (cond == 0xe || cond == 0xf || cond == UINT32_MAX)
14375 return EmulateInstruction::UnconditionalCondition;
14376 return cond;
14377 }
14378
TestEmulation(Stream * out_stream,ArchSpec & arch,OptionValueDictionary * test_data)14379 bool EmulateInstructionARM::TestEmulation(Stream *out_stream, ArchSpec &arch,
14380 OptionValueDictionary *test_data) {
14381 if (!test_data) {
14382 out_stream->Printf("TestEmulation: Missing test data.\n");
14383 return false;
14384 }
14385
14386 static ConstString opcode_key("opcode");
14387 static ConstString before_key("before_state");
14388 static ConstString after_key("after_state");
14389
14390 OptionValueSP value_sp = test_data->GetValueForKey(opcode_key);
14391
14392 uint32_t test_opcode;
14393 if ((value_sp.get() == nullptr) ||
14394 (value_sp->GetType() != OptionValue::eTypeUInt64)) {
14395 out_stream->Printf("TestEmulation: Error reading opcode from test file.\n");
14396 return false;
14397 }
14398 test_opcode = value_sp->GetUInt64Value();
14399
14400 if (arch.GetTriple().getArch() == llvm::Triple::thumb ||
14401 arch.IsAlwaysThumbInstructions()) {
14402 m_opcode_mode = eModeThumb;
14403 if (test_opcode < 0x10000)
14404 m_opcode.SetOpcode16(test_opcode, endian::InlHostByteOrder());
14405 else
14406 m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder());
14407 } else if (arch.GetTriple().getArch() == llvm::Triple::arm) {
14408 m_opcode_mode = eModeARM;
14409 m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder());
14410 } else {
14411 out_stream->Printf("TestEmulation: Invalid arch.\n");
14412 return false;
14413 }
14414
14415 EmulationStateARM before_state;
14416 EmulationStateARM after_state;
14417
14418 value_sp = test_data->GetValueForKey(before_key);
14419 if ((value_sp.get() == nullptr) ||
14420 (value_sp->GetType() != OptionValue::eTypeDictionary)) {
14421 out_stream->Printf("TestEmulation: Failed to find 'before' state.\n");
14422 return false;
14423 }
14424
14425 OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary();
14426 if (!before_state.LoadStateFromDictionary(state_dictionary)) {
14427 out_stream->Printf("TestEmulation: Failed loading 'before' state.\n");
14428 return false;
14429 }
14430
14431 value_sp = test_data->GetValueForKey(after_key);
14432 if ((value_sp.get() == nullptr) ||
14433 (value_sp->GetType() != OptionValue::eTypeDictionary)) {
14434 out_stream->Printf("TestEmulation: Failed to find 'after' state.\n");
14435 return false;
14436 }
14437
14438 state_dictionary = value_sp->GetAsDictionary();
14439 if (!after_state.LoadStateFromDictionary(state_dictionary)) {
14440 out_stream->Printf("TestEmulation: Failed loading 'after' state.\n");
14441 return false;
14442 }
14443
14444 SetBaton((void *)&before_state);
14445 SetCallbacks(&EmulationStateARM::ReadPseudoMemory,
14446 &EmulationStateARM::WritePseudoMemory,
14447 &EmulationStateARM::ReadPseudoRegister,
14448 &EmulationStateARM::WritePseudoRegister);
14449
14450 bool success = EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC);
14451 if (!success) {
14452 out_stream->Printf("TestEmulation: EvaluateInstruction() failed.\n");
14453 return false;
14454 }
14455
14456 success = before_state.CompareState(after_state, out_stream);
14457 if (!success)
14458 out_stream->Printf(
14459 "TestEmulation: State after emulation does not match 'after' state.\n");
14460
14461 return success;
14462 }
14463 //
14464 //
14465 // const char *
14466 // EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)
14467 //{
14468 // if (reg_kind == eRegisterKindGeneric)
14469 // {
14470 // switch (reg_num)
14471 // {
14472 // case LLDB_REGNUM_GENERIC_PC: return "pc";
14473 // case LLDB_REGNUM_GENERIC_SP: return "sp";
14474 // case LLDB_REGNUM_GENERIC_FP: return "fp";
14475 // case LLDB_REGNUM_GENERIC_RA: return "lr";
14476 // case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";
14477 // default: return NULL;
14478 // }
14479 // }
14480 // else if (reg_kind == eRegisterKindDWARF)
14481 // {
14482 // return GetARMDWARFRegisterName (reg_num);
14483 // }
14484 // return NULL;
14485 //}
14486 //
CreateFunctionEntryUnwind(UnwindPlan & unwind_plan)14487 bool EmulateInstructionARM::CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) {
14488 unwind_plan.Clear();
14489 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
14490
14491 UnwindPlan::RowSP row(new UnwindPlan::Row);
14492
14493 // Our previous Call Frame Address is the stack pointer
14494 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp, 0);
14495
14496 unwind_plan.AppendRow(row);
14497 unwind_plan.SetSourceName("EmulateInstructionARM");
14498 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
14499 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
14500 unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
14501 unwind_plan.SetReturnAddressRegister(dwarf_lr);
14502 return true;
14503 }
14504