Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
39644 views
1
//===-- EmulateInstructionARM.cpp -----------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include <cstdlib>
10
#include <optional>
11
12
#include "EmulateInstructionARM.h"
13
#include "EmulationStateARM.h"
14
#include "lldb/Core/Address.h"
15
#include "lldb/Core/PluginManager.h"
16
#include "lldb/Host/PosixApi.h"
17
#include "lldb/Interpreter/OptionValueArray.h"
18
#include "lldb/Interpreter/OptionValueDictionary.h"
19
#include "lldb/Symbol/UnwindPlan.h"
20
#include "lldb/Utility/ArchSpec.h"
21
#include "lldb/Utility/Stream.h"
22
23
#include "Plugins/Process/Utility/ARMDefines.h"
24
#include "Plugins/Process/Utility/ARMUtils.h"
25
#include "Utility/ARM_DWARF_Registers.h"
26
27
#include "llvm/ADT/STLExtras.h"
28
#include "llvm/Support/MathExtras.h"
29
30
using namespace lldb;
31
using namespace lldb_private;
32
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 std::optional<RegisterInfo> GetARMDWARFRegisterInfo(unsigned reg_num) {
46
RegisterInfo reg_info;
47
::memset(&reg_info, 0, sizeof(RegisterInfo));
48
::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
49
50
if (reg_num >= dwarf_q0 && reg_num <= dwarf_q15) {
51
reg_info.byte_size = 16;
52
reg_info.format = eFormatVectorOfUInt8;
53
reg_info.encoding = eEncodingVector;
54
}
55
56
if (reg_num >= dwarf_d0 && reg_num <= dwarf_d31) {
57
reg_info.byte_size = 8;
58
reg_info.format = eFormatFloat;
59
reg_info.encoding = eEncodingIEEE754;
60
} else if (reg_num >= dwarf_s0 && reg_num <= dwarf_s31) {
61
reg_info.byte_size = 4;
62
reg_info.format = eFormatFloat;
63
reg_info.encoding = eEncodingIEEE754;
64
} else if (reg_num >= dwarf_f0 && reg_num <= dwarf_f7) {
65
reg_info.byte_size = 12;
66
reg_info.format = eFormatFloat;
67
reg_info.encoding = eEncodingIEEE754;
68
} else {
69
reg_info.byte_size = 4;
70
reg_info.format = eFormatHex;
71
reg_info.encoding = eEncodingUint;
72
}
73
74
reg_info.kinds[eRegisterKindDWARF] = reg_num;
75
76
switch (reg_num) {
77
case dwarf_r0:
78
reg_info.name = "r0";
79
break;
80
case dwarf_r1:
81
reg_info.name = "r1";
82
break;
83
case dwarf_r2:
84
reg_info.name = "r2";
85
break;
86
case dwarf_r3:
87
reg_info.name = "r3";
88
break;
89
case dwarf_r4:
90
reg_info.name = "r4";
91
break;
92
case dwarf_r5:
93
reg_info.name = "r5";
94
break;
95
case dwarf_r6:
96
reg_info.name = "r6";
97
break;
98
case dwarf_r7:
99
reg_info.name = "r7";
100
reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
101
break;
102
case dwarf_r8:
103
reg_info.name = "r8";
104
break;
105
case dwarf_r9:
106
reg_info.name = "r9";
107
break;
108
case dwarf_r10:
109
reg_info.name = "r10";
110
break;
111
case dwarf_r11:
112
reg_info.name = "r11";
113
break;
114
case dwarf_r12:
115
reg_info.name = "r12";
116
break;
117
case dwarf_sp:
118
reg_info.name = "sp";
119
reg_info.alt_name = "r13";
120
reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
121
break;
122
case dwarf_lr:
123
reg_info.name = "lr";
124
reg_info.alt_name = "r14";
125
reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;
126
break;
127
case dwarf_pc:
128
reg_info.name = "pc";
129
reg_info.alt_name = "r15";
130
reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
131
break;
132
case dwarf_cpsr:
133
reg_info.name = "cpsr";
134
reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
135
break;
136
137
case dwarf_s0:
138
reg_info.name = "s0";
139
break;
140
case dwarf_s1:
141
reg_info.name = "s1";
142
break;
143
case dwarf_s2:
144
reg_info.name = "s2";
145
break;
146
case dwarf_s3:
147
reg_info.name = "s3";
148
break;
149
case dwarf_s4:
150
reg_info.name = "s4";
151
break;
152
case dwarf_s5:
153
reg_info.name = "s5";
154
break;
155
case dwarf_s6:
156
reg_info.name = "s6";
157
break;
158
case dwarf_s7:
159
reg_info.name = "s7";
160
break;
161
case dwarf_s8:
162
reg_info.name = "s8";
163
break;
164
case dwarf_s9:
165
reg_info.name = "s9";
166
break;
167
case dwarf_s10:
168
reg_info.name = "s10";
169
break;
170
case dwarf_s11:
171
reg_info.name = "s11";
172
break;
173
case dwarf_s12:
174
reg_info.name = "s12";
175
break;
176
case dwarf_s13:
177
reg_info.name = "s13";
178
break;
179
case dwarf_s14:
180
reg_info.name = "s14";
181
break;
182
case dwarf_s15:
183
reg_info.name = "s15";
184
break;
185
case dwarf_s16:
186
reg_info.name = "s16";
187
break;
188
case dwarf_s17:
189
reg_info.name = "s17";
190
break;
191
case dwarf_s18:
192
reg_info.name = "s18";
193
break;
194
case dwarf_s19:
195
reg_info.name = "s19";
196
break;
197
case dwarf_s20:
198
reg_info.name = "s20";
199
break;
200
case dwarf_s21:
201
reg_info.name = "s21";
202
break;
203
case dwarf_s22:
204
reg_info.name = "s22";
205
break;
206
case dwarf_s23:
207
reg_info.name = "s23";
208
break;
209
case dwarf_s24:
210
reg_info.name = "s24";
211
break;
212
case dwarf_s25:
213
reg_info.name = "s25";
214
break;
215
case dwarf_s26:
216
reg_info.name = "s26";
217
break;
218
case dwarf_s27:
219
reg_info.name = "s27";
220
break;
221
case dwarf_s28:
222
reg_info.name = "s28";
223
break;
224
case dwarf_s29:
225
reg_info.name = "s29";
226
break;
227
case dwarf_s30:
228
reg_info.name = "s30";
229
break;
230
case dwarf_s31:
231
reg_info.name = "s31";
232
break;
233
234
// FPA Registers 0-7
235
case dwarf_f0:
236
reg_info.name = "f0";
237
break;
238
case dwarf_f1:
239
reg_info.name = "f1";
240
break;
241
case dwarf_f2:
242
reg_info.name = "f2";
243
break;
244
case dwarf_f3:
245
reg_info.name = "f3";
246
break;
247
case dwarf_f4:
248
reg_info.name = "f4";
249
break;
250
case dwarf_f5:
251
reg_info.name = "f5";
252
break;
253
case dwarf_f6:
254
reg_info.name = "f6";
255
break;
256
case dwarf_f7:
257
reg_info.name = "f7";
258
break;
259
260
// Intel wireless MMX general purpose registers 0 - 7 XScale accumulator
261
// register 0 - 7 (they do overlap with wCGR0 - wCGR7)
262
case dwarf_wCGR0:
263
reg_info.name = "wCGR0/ACC0";
264
break;
265
case dwarf_wCGR1:
266
reg_info.name = "wCGR1/ACC1";
267
break;
268
case dwarf_wCGR2:
269
reg_info.name = "wCGR2/ACC2";
270
break;
271
case dwarf_wCGR3:
272
reg_info.name = "wCGR3/ACC3";
273
break;
274
case dwarf_wCGR4:
275
reg_info.name = "wCGR4/ACC4";
276
break;
277
case dwarf_wCGR5:
278
reg_info.name = "wCGR5/ACC5";
279
break;
280
case dwarf_wCGR6:
281
reg_info.name = "wCGR6/ACC6";
282
break;
283
case dwarf_wCGR7:
284
reg_info.name = "wCGR7/ACC7";
285
break;
286
287
// Intel wireless MMX data registers 0 - 15
288
case dwarf_wR0:
289
reg_info.name = "wR0";
290
break;
291
case dwarf_wR1:
292
reg_info.name = "wR1";
293
break;
294
case dwarf_wR2:
295
reg_info.name = "wR2";
296
break;
297
case dwarf_wR3:
298
reg_info.name = "wR3";
299
break;
300
case dwarf_wR4:
301
reg_info.name = "wR4";
302
break;
303
case dwarf_wR5:
304
reg_info.name = "wR5";
305
break;
306
case dwarf_wR6:
307
reg_info.name = "wR6";
308
break;
309
case dwarf_wR7:
310
reg_info.name = "wR7";
311
break;
312
case dwarf_wR8:
313
reg_info.name = "wR8";
314
break;
315
case dwarf_wR9:
316
reg_info.name = "wR9";
317
break;
318
case dwarf_wR10:
319
reg_info.name = "wR10";
320
break;
321
case dwarf_wR11:
322
reg_info.name = "wR11";
323
break;
324
case dwarf_wR12:
325
reg_info.name = "wR12";
326
break;
327
case dwarf_wR13:
328
reg_info.name = "wR13";
329
break;
330
case dwarf_wR14:
331
reg_info.name = "wR14";
332
break;
333
case dwarf_wR15:
334
reg_info.name = "wR15";
335
break;
336
337
case dwarf_spsr:
338
reg_info.name = "spsr";
339
break;
340
case dwarf_spsr_fiq:
341
reg_info.name = "spsr_fiq";
342
break;
343
case dwarf_spsr_irq:
344
reg_info.name = "spsr_irq";
345
break;
346
case dwarf_spsr_abt:
347
reg_info.name = "spsr_abt";
348
break;
349
case dwarf_spsr_und:
350
reg_info.name = "spsr_und";
351
break;
352
case dwarf_spsr_svc:
353
reg_info.name = "spsr_svc";
354
break;
355
356
case dwarf_r8_usr:
357
reg_info.name = "r8_usr";
358
break;
359
case dwarf_r9_usr:
360
reg_info.name = "r9_usr";
361
break;
362
case dwarf_r10_usr:
363
reg_info.name = "r10_usr";
364
break;
365
case dwarf_r11_usr:
366
reg_info.name = "r11_usr";
367
break;
368
case dwarf_r12_usr:
369
reg_info.name = "r12_usr";
370
break;
371
case dwarf_r13_usr:
372
reg_info.name = "r13_usr";
373
break;
374
case dwarf_r14_usr:
375
reg_info.name = "r14_usr";
376
break;
377
case dwarf_r8_fiq:
378
reg_info.name = "r8_fiq";
379
break;
380
case dwarf_r9_fiq:
381
reg_info.name = "r9_fiq";
382
break;
383
case dwarf_r10_fiq:
384
reg_info.name = "r10_fiq";
385
break;
386
case dwarf_r11_fiq:
387
reg_info.name = "r11_fiq";
388
break;
389
case dwarf_r12_fiq:
390
reg_info.name = "r12_fiq";
391
break;
392
case dwarf_r13_fiq:
393
reg_info.name = "r13_fiq";
394
break;
395
case dwarf_r14_fiq:
396
reg_info.name = "r14_fiq";
397
break;
398
case dwarf_r13_irq:
399
reg_info.name = "r13_irq";
400
break;
401
case dwarf_r14_irq:
402
reg_info.name = "r14_irq";
403
break;
404
case dwarf_r13_abt:
405
reg_info.name = "r13_abt";
406
break;
407
case dwarf_r14_abt:
408
reg_info.name = "r14_abt";
409
break;
410
case dwarf_r13_und:
411
reg_info.name = "r13_und";
412
break;
413
case dwarf_r14_und:
414
reg_info.name = "r14_und";
415
break;
416
case dwarf_r13_svc:
417
reg_info.name = "r13_svc";
418
break;
419
case dwarf_r14_svc:
420
reg_info.name = "r14_svc";
421
break;
422
423
// Intel wireless MMX control register in co-processor 0 - 7
424
case dwarf_wC0:
425
reg_info.name = "wC0";
426
break;
427
case dwarf_wC1:
428
reg_info.name = "wC1";
429
break;
430
case dwarf_wC2:
431
reg_info.name = "wC2";
432
break;
433
case dwarf_wC3:
434
reg_info.name = "wC3";
435
break;
436
case dwarf_wC4:
437
reg_info.name = "wC4";
438
break;
439
case dwarf_wC5:
440
reg_info.name = "wC5";
441
break;
442
case dwarf_wC6:
443
reg_info.name = "wC6";
444
break;
445
case dwarf_wC7:
446
reg_info.name = "wC7";
447
break;
448
449
// VFP-v3/Neon
450
case dwarf_d0:
451
reg_info.name = "d0";
452
break;
453
case dwarf_d1:
454
reg_info.name = "d1";
455
break;
456
case dwarf_d2:
457
reg_info.name = "d2";
458
break;
459
case dwarf_d3:
460
reg_info.name = "d3";
461
break;
462
case dwarf_d4:
463
reg_info.name = "d4";
464
break;
465
case dwarf_d5:
466
reg_info.name = "d5";
467
break;
468
case dwarf_d6:
469
reg_info.name = "d6";
470
break;
471
case dwarf_d7:
472
reg_info.name = "d7";
473
break;
474
case dwarf_d8:
475
reg_info.name = "d8";
476
break;
477
case dwarf_d9:
478
reg_info.name = "d9";
479
break;
480
case dwarf_d10:
481
reg_info.name = "d10";
482
break;
483
case dwarf_d11:
484
reg_info.name = "d11";
485
break;
486
case dwarf_d12:
487
reg_info.name = "d12";
488
break;
489
case dwarf_d13:
490
reg_info.name = "d13";
491
break;
492
case dwarf_d14:
493
reg_info.name = "d14";
494
break;
495
case dwarf_d15:
496
reg_info.name = "d15";
497
break;
498
case dwarf_d16:
499
reg_info.name = "d16";
500
break;
501
case dwarf_d17:
502
reg_info.name = "d17";
503
break;
504
case dwarf_d18:
505
reg_info.name = "d18";
506
break;
507
case dwarf_d19:
508
reg_info.name = "d19";
509
break;
510
case dwarf_d20:
511
reg_info.name = "d20";
512
break;
513
case dwarf_d21:
514
reg_info.name = "d21";
515
break;
516
case dwarf_d22:
517
reg_info.name = "d22";
518
break;
519
case dwarf_d23:
520
reg_info.name = "d23";
521
break;
522
case dwarf_d24:
523
reg_info.name = "d24";
524
break;
525
case dwarf_d25:
526
reg_info.name = "d25";
527
break;
528
case dwarf_d26:
529
reg_info.name = "d26";
530
break;
531
case dwarf_d27:
532
reg_info.name = "d27";
533
break;
534
case dwarf_d28:
535
reg_info.name = "d28";
536
break;
537
case dwarf_d29:
538
reg_info.name = "d29";
539
break;
540
case dwarf_d30:
541
reg_info.name = "d30";
542
break;
543
case dwarf_d31:
544
reg_info.name = "d31";
545
break;
546
547
// NEON 128-bit vector registers (overlays the d registers)
548
case dwarf_q0:
549
reg_info.name = "q0";
550
break;
551
case dwarf_q1:
552
reg_info.name = "q1";
553
break;
554
case dwarf_q2:
555
reg_info.name = "q2";
556
break;
557
case dwarf_q3:
558
reg_info.name = "q3";
559
break;
560
case dwarf_q4:
561
reg_info.name = "q4";
562
break;
563
case dwarf_q5:
564
reg_info.name = "q5";
565
break;
566
case dwarf_q6:
567
reg_info.name = "q6";
568
break;
569
case dwarf_q7:
570
reg_info.name = "q7";
571
break;
572
case dwarf_q8:
573
reg_info.name = "q8";
574
break;
575
case dwarf_q9:
576
reg_info.name = "q9";
577
break;
578
case dwarf_q10:
579
reg_info.name = "q10";
580
break;
581
case dwarf_q11:
582
reg_info.name = "q11";
583
break;
584
case dwarf_q12:
585
reg_info.name = "q12";
586
break;
587
case dwarf_q13:
588
reg_info.name = "q13";
589
break;
590
case dwarf_q14:
591
reg_info.name = "q14";
592
break;
593
case dwarf_q15:
594
reg_info.name = "q15";
595
break;
596
597
default:
598
return {};
599
}
600
return reg_info;
601
}
602
603
// A8.6.50
604
// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
605
static uint32_t CountITSize(uint32_t ITMask) {
606
// First count the trailing zeros of the IT mask.
607
uint32_t TZ = llvm::countr_zero(ITMask);
608
if (TZ > 3) {
609
return 0;
610
}
611
return (4 - TZ);
612
}
613
614
// Init ITState. Note that at least one bit is always 1 in mask.
615
bool ITSession::InitIT(uint32_t bits7_0) {
616
ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
617
if (ITCounter == 0)
618
return false;
619
620
// A8.6.50 IT
621
unsigned short FirstCond = Bits32(bits7_0, 7, 4);
622
if (FirstCond == 0xF) {
623
return false;
624
}
625
if (FirstCond == 0xE && ITCounter != 1) {
626
return false;
627
}
628
629
ITState = bits7_0;
630
return true;
631
}
632
633
// Update ITState if necessary.
634
void ITSession::ITAdvance() {
635
// assert(ITCounter);
636
--ITCounter;
637
if (ITCounter == 0)
638
ITState = 0;
639
else {
640
unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
641
SetBits32(ITState, 4, 0, NewITState4_0);
642
}
643
}
644
645
// Return true if we're inside an IT Block.
646
bool ITSession::InITBlock() { return ITCounter != 0; }
647
648
// Return true if we're the last instruction inside an IT Block.
649
bool ITSession::LastInITBlock() { return ITCounter == 1; }
650
651
// Get condition bits for the current thumb instruction.
652
uint32_t ITSession::GetCond() {
653
if (InITBlock())
654
return Bits32(ITState, 7, 4);
655
else
656
return COND_AL;
657
}
658
659
// ARM constants used during decoding
660
#define REG_RD 0
661
#define LDM_REGLIST 1
662
#define SP_REG 13
663
#define LR_REG 14
664
#define PC_REG 15
665
#define PC_REGLIST_BIT 0x8000
666
667
#define ARMv4 (1u << 0)
668
#define ARMv4T (1u << 1)
669
#define ARMv5T (1u << 2)
670
#define ARMv5TE (1u << 3)
671
#define ARMv5TEJ (1u << 4)
672
#define ARMv6 (1u << 5)
673
#define ARMv6K (1u << 6)
674
#define ARMv6T2 (1u << 7)
675
#define ARMv7 (1u << 8)
676
#define ARMv7S (1u << 9)
677
#define ARMv8 (1u << 10)
678
#define ARMvAll (0xffffffffu)
679
680
#define ARMV4T_ABOVE \
681
(ARMv4T | ARMv5T | ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | \
682
ARMv7S | ARMv8)
683
#define ARMV5_ABOVE \
684
(ARMv5T | ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | \
685
ARMv8)
686
#define ARMV5TE_ABOVE \
687
(ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
688
#define ARMV5J_ABOVE \
689
(ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
690
#define ARMV6_ABOVE (ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
691
#define ARMV6T2_ABOVE (ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
692
#define ARMV7_ABOVE (ARMv7 | ARMv7S | ARMv8)
693
694
#define No_VFP 0
695
#define VFPv1 (1u << 1)
696
#define VFPv2 (1u << 2)
697
#define VFPv3 (1u << 3)
698
#define AdvancedSIMD (1u << 4)
699
700
#define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD)
701
#define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD)
702
#define VFPv2v3 (VFPv2 | VFPv3)
703
704
//
705
// EmulateInstructionARM implementation
706
//
707
708
void EmulateInstructionARM::Initialize() {
709
PluginManager::RegisterPlugin(GetPluginNameStatic(),
710
GetPluginDescriptionStatic(), CreateInstance);
711
}
712
713
void EmulateInstructionARM::Terminate() {
714
PluginManager::UnregisterPlugin(CreateInstance);
715
}
716
717
llvm::StringRef EmulateInstructionARM::GetPluginDescriptionStatic() {
718
return "Emulate instructions for the ARM architecture.";
719
}
720
721
EmulateInstruction *
722
EmulateInstructionARM::CreateInstance(const ArchSpec &arch,
723
InstructionType inst_type) {
724
if (EmulateInstructionARM::SupportsEmulatingInstructionsOfTypeStatic(
725
inst_type)) {
726
if (arch.GetTriple().getArch() == llvm::Triple::arm) {
727
std::unique_ptr<EmulateInstructionARM> emulate_insn_up(
728
new EmulateInstructionARM(arch));
729
730
if (emulate_insn_up)
731
return emulate_insn_up.release();
732
} else if (arch.GetTriple().getArch() == llvm::Triple::thumb) {
733
std::unique_ptr<EmulateInstructionARM> emulate_insn_up(
734
new EmulateInstructionARM(arch));
735
736
if (emulate_insn_up)
737
return emulate_insn_up.release();
738
}
739
}
740
741
return nullptr;
742
}
743
744
bool EmulateInstructionARM::SetTargetTriple(const ArchSpec &arch) {
745
if (arch.GetTriple().getArch() == llvm::Triple::arm)
746
return true;
747
else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
748
return true;
749
750
return false;
751
}
752
753
// Write "bits (32) UNKNOWN" to memory address "address". Helper function for
754
// many ARM instructions.
755
bool EmulateInstructionARM::WriteBits32UnknownToMemory(addr_t address) {
756
EmulateInstruction::Context context;
757
context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
758
context.SetNoArgs();
759
760
uint32_t random_data = rand();
761
const uint32_t addr_byte_size = GetAddressByteSize();
762
763
return MemAWrite(context, address, random_data, addr_byte_size);
764
}
765
766
// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM
767
// instructions.
768
bool EmulateInstructionARM::WriteBits32Unknown(int n) {
769
EmulateInstruction::Context context;
770
context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
771
context.SetNoArgs();
772
773
bool success;
774
uint32_t data =
775
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
776
777
if (!success)
778
return false;
779
780
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, data))
781
return false;
782
783
return true;
784
}
785
786
std::optional<RegisterInfo>
787
EmulateInstructionARM::GetRegisterInfo(lldb::RegisterKind reg_kind,
788
uint32_t reg_num) {
789
if (reg_kind == eRegisterKindGeneric) {
790
switch (reg_num) {
791
case LLDB_REGNUM_GENERIC_PC:
792
reg_kind = eRegisterKindDWARF;
793
reg_num = dwarf_pc;
794
break;
795
case LLDB_REGNUM_GENERIC_SP:
796
reg_kind = eRegisterKindDWARF;
797
reg_num = dwarf_sp;
798
break;
799
case LLDB_REGNUM_GENERIC_FP:
800
reg_kind = eRegisterKindDWARF;
801
reg_num = dwarf_r7;
802
break;
803
case LLDB_REGNUM_GENERIC_RA:
804
reg_kind = eRegisterKindDWARF;
805
reg_num = dwarf_lr;
806
break;
807
case LLDB_REGNUM_GENERIC_FLAGS:
808
reg_kind = eRegisterKindDWARF;
809
reg_num = dwarf_cpsr;
810
break;
811
default:
812
return {};
813
}
814
}
815
816
if (reg_kind == eRegisterKindDWARF)
817
return GetARMDWARFRegisterInfo(reg_num);
818
return {};
819
}
820
821
uint32_t EmulateInstructionARM::GetFramePointerRegisterNumber() const {
822
if (m_arch.GetTriple().isAndroid())
823
return LLDB_INVALID_REGNUM; // Don't use frame pointer on android
824
bool is_apple = false;
825
if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)
826
is_apple = true;
827
switch (m_arch.GetTriple().getOS()) {
828
case llvm::Triple::Darwin:
829
case llvm::Triple::MacOSX:
830
case llvm::Triple::IOS:
831
case llvm::Triple::TvOS:
832
case llvm::Triple::WatchOS:
833
case llvm::Triple::XROS:
834
case llvm::Triple::BridgeOS:
835
is_apple = true;
836
break;
837
default:
838
break;
839
}
840
841
/* On Apple iOS et al, the frame pointer register is always r7.
842
* Typically on other ARM systems, thumb code uses r7; arm code uses r11.
843
* Windows on ARM, which is in thumb mode, uses r11 though.
844
*/
845
846
uint32_t fp_regnum = 11;
847
848
if (is_apple)
849
fp_regnum = 7;
850
851
if (m_opcode_mode == eModeThumb && !m_arch.GetTriple().isOSWindows())
852
fp_regnum = 7;
853
854
return fp_regnum;
855
}
856
857
uint32_t EmulateInstructionARM::GetFramePointerDWARFRegisterNumber() const {
858
bool is_apple = false;
859
if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)
860
is_apple = true;
861
switch (m_arch.GetTriple().getOS()) {
862
case llvm::Triple::Darwin:
863
case llvm::Triple::MacOSX:
864
case llvm::Triple::IOS:
865
is_apple = true;
866
break;
867
default:
868
break;
869
}
870
871
/* On Apple iOS et al, the frame pointer register is always r7.
872
* Typically on other ARM systems, thumb code uses r7; arm code uses r11.
873
* Windows on ARM, which is in thumb mode, uses r11 though.
874
*/
875
876
uint32_t fp_regnum = dwarf_r11;
877
878
if (is_apple)
879
fp_regnum = dwarf_r7;
880
881
if (m_opcode_mode == eModeThumb && !m_arch.GetTriple().isOSWindows())
882
fp_regnum = dwarf_r7;
883
884
return fp_regnum;
885
}
886
887
// Push Multiple Registers stores multiple registers to the stack, storing to
888
// consecutive memory locations ending just below the address in SP, and
889
// updates
890
// SP to point to the start of the stored data.
891
bool EmulateInstructionARM::EmulatePUSH(const uint32_t opcode,
892
const ARMEncoding encoding) {
893
#if 0
894
// ARM pseudo code...
895
if (ConditionPassed())
896
{
897
EncodingSpecificOperations();
898
NullCheckIfThumbEE(13);
899
address = SP - 4*BitCount(registers);
900
901
for (i = 0 to 14)
902
{
903
if (registers<i> == '1')
904
{
905
if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
906
MemA[address,4] = bits(32) UNKNOWN;
907
else
908
MemA[address,4] = R[i];
909
address = address + 4;
910
}
911
}
912
913
if (registers<15> == '1') // Only possible for encoding A1 or A2
914
MemA[address,4] = PCStoreValue();
915
916
SP = SP - 4*BitCount(registers);
917
}
918
#endif
919
920
bool success = false;
921
if (ConditionPassed(opcode)) {
922
const uint32_t addr_byte_size = GetAddressByteSize();
923
const addr_t sp = ReadCoreReg(SP_REG, &success);
924
if (!success)
925
return false;
926
uint32_t registers = 0;
927
uint32_t Rt; // the source register
928
switch (encoding) {
929
case eEncodingT1:
930
registers = Bits32(opcode, 7, 0);
931
// The M bit represents LR.
932
if (Bit32(opcode, 8))
933
registers |= (1u << 14);
934
// if BitCount(registers) < 1 then UNPREDICTABLE;
935
if (BitCount(registers) < 1)
936
return false;
937
break;
938
case eEncodingT2:
939
// Ignore bits 15 & 13.
940
registers = Bits32(opcode, 15, 0) & ~0xa000;
941
// if BitCount(registers) < 2 then UNPREDICTABLE;
942
if (BitCount(registers) < 2)
943
return false;
944
break;
945
case eEncodingT3:
946
Rt = Bits32(opcode, 15, 12);
947
// if BadReg(t) then UNPREDICTABLE;
948
if (BadReg(Rt))
949
return false;
950
registers = (1u << Rt);
951
break;
952
case eEncodingA1:
953
registers = Bits32(opcode, 15, 0);
954
// Instead of return false, let's handle the following case as well,
955
// which amounts to pushing one reg onto the full descending stacks.
956
// if BitCount(register_list) < 2 then SEE STMDB / STMFD;
957
break;
958
case eEncodingA2:
959
Rt = Bits32(opcode, 15, 12);
960
// if t == 13 then UNPREDICTABLE;
961
if (Rt == dwarf_sp)
962
return false;
963
registers = (1u << Rt);
964
break;
965
default:
966
return false;
967
}
968
addr_t sp_offset = addr_byte_size * BitCount(registers);
969
addr_t addr = sp - sp_offset;
970
uint32_t i;
971
972
EmulateInstruction::Context context;
973
context.type = EmulateInstruction::eContextPushRegisterOnStack;
974
std::optional<RegisterInfo> sp_reg =
975
GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);
976
for (i = 0; i < 15; ++i) {
977
if (BitIsSet(registers, i)) {
978
std::optional<RegisterInfo> reg_info =
979
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i);
980
context.SetRegisterToRegisterPlusOffset(*reg_info, *sp_reg, addr - sp);
981
uint32_t reg_value = ReadCoreReg(i, &success);
982
if (!success)
983
return false;
984
if (!MemAWrite(context, addr, reg_value, addr_byte_size))
985
return false;
986
addr += addr_byte_size;
987
}
988
}
989
990
if (BitIsSet(registers, 15)) {
991
std::optional<RegisterInfo> reg_info =
992
GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);
993
context.SetRegisterToRegisterPlusOffset(*reg_info, *sp_reg, addr - sp);
994
const uint32_t pc = ReadCoreReg(PC_REG, &success);
995
if (!success)
996
return false;
997
if (!MemAWrite(context, addr, pc, addr_byte_size))
998
return false;
999
}
1000
1001
context.type = EmulateInstruction::eContextAdjustStackPointer;
1002
context.SetImmediateSigned(-sp_offset);
1003
1004
if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1005
LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
1006
return false;
1007
}
1008
return true;
1009
}
1010
1011
// Pop Multiple Registers loads multiple registers from the stack, loading from
1012
// consecutive memory locations staring at the address in SP, and updates
1013
// SP to point just above the loaded data.
1014
bool EmulateInstructionARM::EmulatePOP(const uint32_t opcode,
1015
const ARMEncoding encoding) {
1016
#if 0
1017
// ARM pseudo code...
1018
if (ConditionPassed())
1019
{
1020
EncodingSpecificOperations(); NullCheckIfThumbEE(13);
1021
address = SP;
1022
for i = 0 to 14
1023
if registers<i> == '1' then
1024
R[i] = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
1025
if registers<15> == '1' then
1026
if UnalignedAllowed then
1027
LoadWritePC(MemU[address,4]);
1028
else
1029
LoadWritePC(MemA[address,4]);
1030
if registers<13> == '0' then SP = SP + 4*BitCount(registers);
1031
if registers<13> == '1' then SP = bits(32) UNKNOWN;
1032
}
1033
#endif
1034
1035
bool success = false;
1036
1037
if (ConditionPassed(opcode)) {
1038
const uint32_t addr_byte_size = GetAddressByteSize();
1039
const addr_t sp = ReadCoreReg(SP_REG, &success);
1040
if (!success)
1041
return false;
1042
uint32_t registers = 0;
1043
uint32_t Rt; // the destination register
1044
switch (encoding) {
1045
case eEncodingT1:
1046
registers = Bits32(opcode, 7, 0);
1047
// The P bit represents PC.
1048
if (Bit32(opcode, 8))
1049
registers |= (1u << 15);
1050
// if BitCount(registers) < 1 then UNPREDICTABLE;
1051
if (BitCount(registers) < 1)
1052
return false;
1053
break;
1054
case eEncodingT2:
1055
// Ignore bit 13.
1056
registers = Bits32(opcode, 15, 0) & ~0x2000;
1057
// if BitCount(registers) < 2 || (P == '1' && M == '1') then
1058
// UNPREDICTABLE;
1059
if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
1060
return false;
1061
// if registers<15> == '1' && InITBlock() && !LastInITBlock() then
1062
// UNPREDICTABLE;
1063
if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
1064
return false;
1065
break;
1066
case eEncodingT3:
1067
Rt = Bits32(opcode, 15, 12);
1068
// if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then
1069
// UNPREDICTABLE;
1070
if (Rt == 13)
1071
return false;
1072
if (Rt == 15 && InITBlock() && !LastInITBlock())
1073
return false;
1074
registers = (1u << Rt);
1075
break;
1076
case eEncodingA1:
1077
registers = Bits32(opcode, 15, 0);
1078
// Instead of return false, let's handle the following case as well,
1079
// which amounts to popping one reg from the full descending stacks.
1080
// if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
1081
1082
// if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
1083
if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
1084
return false;
1085
break;
1086
case eEncodingA2:
1087
Rt = Bits32(opcode, 15, 12);
1088
// if t == 13 then UNPREDICTABLE;
1089
if (Rt == dwarf_sp)
1090
return false;
1091
registers = (1u << Rt);
1092
break;
1093
default:
1094
return false;
1095
}
1096
addr_t sp_offset = addr_byte_size * BitCount(registers);
1097
addr_t addr = sp;
1098
uint32_t i, data;
1099
1100
EmulateInstruction::Context context;
1101
context.type = EmulateInstruction::eContextPopRegisterOffStack;
1102
1103
std::optional<RegisterInfo> sp_reg =
1104
GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);
1105
1106
for (i = 0; i < 15; ++i) {
1107
if (BitIsSet(registers, i)) {
1108
context.SetAddress(addr);
1109
data = MemARead(context, addr, 4, 0, &success);
1110
if (!success)
1111
return false;
1112
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
1113
data))
1114
return false;
1115
addr += addr_byte_size;
1116
}
1117
}
1118
1119
if (BitIsSet(registers, 15)) {
1120
context.SetRegisterPlusOffset(*sp_reg, addr - sp);
1121
data = MemARead(context, addr, 4, 0, &success);
1122
if (!success)
1123
return false;
1124
// In ARMv5T and above, this is an interworking branch.
1125
if (!LoadWritePC(context, data))
1126
return false;
1127
// addr += addr_byte_size;
1128
}
1129
1130
context.type = EmulateInstruction::eContextAdjustStackPointer;
1131
context.SetImmediateSigned(sp_offset);
1132
1133
if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1134
LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1135
return false;
1136
}
1137
return true;
1138
}
1139
1140
// Set r7 or ip to point to saved value residing within the stack.
1141
// ADD (SP plus immediate)
1142
bool EmulateInstructionARM::EmulateADDRdSPImm(const uint32_t opcode,
1143
const ARMEncoding encoding) {
1144
#if 0
1145
// ARM pseudo code...
1146
if (ConditionPassed())
1147
{
1148
EncodingSpecificOperations();
1149
(result, carry, overflow) = AddWithCarry(SP, imm32, '0');
1150
if d == 15 then
1151
ALUWritePC(result); // setflags is always FALSE here
1152
else
1153
R[d] = result;
1154
if setflags then
1155
APSR.N = result<31>;
1156
APSR.Z = IsZeroBit(result);
1157
APSR.C = carry;
1158
APSR.V = overflow;
1159
}
1160
#endif
1161
1162
bool success = false;
1163
1164
if (ConditionPassed(opcode)) {
1165
const addr_t sp = ReadCoreReg(SP_REG, &success);
1166
if (!success)
1167
return false;
1168
uint32_t Rd; // the destination register
1169
uint32_t imm32;
1170
switch (encoding) {
1171
case eEncodingT1:
1172
Rd = 7;
1173
imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
1174
break;
1175
case eEncodingA1:
1176
Rd = Bits32(opcode, 15, 12);
1177
imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1178
break;
1179
default:
1180
return false;
1181
}
1182
addr_t sp_offset = imm32;
1183
addr_t addr = sp + sp_offset; // a pointer to the stack area
1184
1185
EmulateInstruction::Context context;
1186
if (Rd == GetFramePointerRegisterNumber())
1187
context.type = eContextSetFramePointer;
1188
else
1189
context.type = EmulateInstruction::eContextRegisterPlusOffset;
1190
std::optional<RegisterInfo> sp_reg =
1191
GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);
1192
context.SetRegisterPlusOffset(*sp_reg, sp_offset);
1193
1194
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd,
1195
addr))
1196
return false;
1197
}
1198
return true;
1199
}
1200
1201
// Set r7 or ip to the current stack pointer.
1202
// MOV (register)
1203
bool EmulateInstructionARM::EmulateMOVRdSP(const uint32_t opcode,
1204
const ARMEncoding encoding) {
1205
#if 0
1206
// ARM pseudo code...
1207
if (ConditionPassed())
1208
{
1209
EncodingSpecificOperations();
1210
result = R[m];
1211
if d == 15 then
1212
ALUWritePC(result); // setflags is always FALSE here
1213
else
1214
R[d] = result;
1215
if setflags then
1216
APSR.N = result<31>;
1217
APSR.Z = IsZeroBit(result);
1218
// APSR.C unchanged
1219
// APSR.V unchanged
1220
}
1221
#endif
1222
1223
bool success = false;
1224
1225
if (ConditionPassed(opcode)) {
1226
const addr_t sp = ReadCoreReg(SP_REG, &success);
1227
if (!success)
1228
return false;
1229
uint32_t Rd; // the destination register
1230
switch (encoding) {
1231
case eEncodingT1:
1232
Rd = 7;
1233
break;
1234
case eEncodingA1:
1235
Rd = 12;
1236
break;
1237
default:
1238
return false;
1239
}
1240
1241
EmulateInstruction::Context context;
1242
if (Rd == GetFramePointerRegisterNumber())
1243
context.type = EmulateInstruction::eContextSetFramePointer;
1244
else
1245
context.type = EmulateInstruction::eContextRegisterPlusOffset;
1246
std::optional<RegisterInfo> sp_reg =
1247
GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);
1248
context.SetRegisterPlusOffset(*sp_reg, 0);
1249
1250
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
1251
return false;
1252
}
1253
return true;
1254
}
1255
1256
// Move from high register (r8-r15) to low register (r0-r7).
1257
// MOV (register)
1258
bool EmulateInstructionARM::EmulateMOVLowHigh(const uint32_t opcode,
1259
const ARMEncoding encoding) {
1260
return EmulateMOVRdRm(opcode, encoding);
1261
}
1262
1263
// Move from register to register.
1264
// MOV (register)
1265
bool EmulateInstructionARM::EmulateMOVRdRm(const uint32_t opcode,
1266
const ARMEncoding encoding) {
1267
#if 0
1268
// ARM pseudo code...
1269
if (ConditionPassed())
1270
{
1271
EncodingSpecificOperations();
1272
result = R[m];
1273
if d == 15 then
1274
ALUWritePC(result); // setflags is always FALSE here
1275
else
1276
R[d] = result;
1277
if setflags then
1278
APSR.N = result<31>;
1279
APSR.Z = IsZeroBit(result);
1280
// APSR.C unchanged
1281
// APSR.V unchanged
1282
}
1283
#endif
1284
1285
bool success = false;
1286
1287
if (ConditionPassed(opcode)) {
1288
uint32_t Rm; // the source register
1289
uint32_t Rd; // the destination register
1290
bool setflags;
1291
switch (encoding) {
1292
case eEncodingT1:
1293
Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
1294
Rm = Bits32(opcode, 6, 3);
1295
setflags = false;
1296
if (Rd == 15 && InITBlock() && !LastInITBlock())
1297
return false;
1298
break;
1299
case eEncodingT2:
1300
Rd = Bits32(opcode, 2, 0);
1301
Rm = Bits32(opcode, 5, 3);
1302
setflags = true;
1303
if (InITBlock())
1304
return false;
1305
break;
1306
case eEncodingT3:
1307
Rd = Bits32(opcode, 11, 8);
1308
Rm = Bits32(opcode, 3, 0);
1309
setflags = BitIsSet(opcode, 20);
1310
// if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
1311
if (setflags && (BadReg(Rd) || BadReg(Rm)))
1312
return false;
1313
// if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then
1314
// UNPREDICTABLE;
1315
if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
1316
return false;
1317
break;
1318
case eEncodingA1:
1319
Rd = Bits32(opcode, 15, 12);
1320
Rm = Bits32(opcode, 3, 0);
1321
setflags = BitIsSet(opcode, 20);
1322
1323
// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1324
// instructions;
1325
if (Rd == 15 && setflags)
1326
return EmulateSUBSPcLrEtc(opcode, encoding);
1327
break;
1328
default:
1329
return false;
1330
}
1331
uint32_t result = ReadCoreReg(Rm, &success);
1332
if (!success)
1333
return false;
1334
1335
// The context specifies that Rm is to be moved into Rd.
1336
EmulateInstruction::Context context;
1337
if (Rd == 13)
1338
context.type = EmulateInstruction::eContextAdjustStackPointer;
1339
else if (Rd == GetFramePointerRegisterNumber() && Rm == 13)
1340
context.type = EmulateInstruction::eContextSetFramePointer;
1341
else
1342
context.type = EmulateInstruction::eContextRegisterPlusOffset;
1343
std::optional<RegisterInfo> dwarf_reg =
1344
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);
1345
context.SetRegisterPlusOffset(*dwarf_reg, 0);
1346
1347
if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
1348
return false;
1349
}
1350
return true;
1351
}
1352
1353
// Move (immediate) writes an immediate value to the destination register. It
1354
// can optionally update the condition flags based on the value.
1355
// MOV (immediate)
1356
bool EmulateInstructionARM::EmulateMOVRdImm(const uint32_t opcode,
1357
const ARMEncoding encoding) {
1358
#if 0
1359
// ARM pseudo code...
1360
if (ConditionPassed())
1361
{
1362
EncodingSpecificOperations();
1363
result = imm32;
1364
if d == 15 then // Can only occur for ARM encoding
1365
ALUWritePC(result); // setflags is always FALSE here
1366
else
1367
R[d] = result;
1368
if setflags then
1369
APSR.N = result<31>;
1370
APSR.Z = IsZeroBit(result);
1371
APSR.C = carry;
1372
// APSR.V unchanged
1373
}
1374
#endif
1375
1376
if (ConditionPassed(opcode)) {
1377
uint32_t Rd; // the destination register
1378
uint32_t imm32; // the immediate value to be written to Rd
1379
uint32_t carry =
1380
0; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
1381
// for setflags == false, this value is a don't care initialized to
1382
// 0 to silence the static analyzer
1383
bool setflags;
1384
switch (encoding) {
1385
case eEncodingT1:
1386
Rd = Bits32(opcode, 10, 8);
1387
setflags = !InITBlock();
1388
imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
1389
carry = APSR_C;
1390
1391
break;
1392
1393
case eEncodingT2:
1394
Rd = Bits32(opcode, 11, 8);
1395
setflags = BitIsSet(opcode, 20);
1396
imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
1397
if (BadReg(Rd))
1398
return false;
1399
1400
break;
1401
1402
case eEncodingT3: {
1403
// d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8,
1404
// 32);
1405
Rd = Bits32(opcode, 11, 8);
1406
setflags = false;
1407
uint32_t imm4 = Bits32(opcode, 19, 16);
1408
uint32_t imm3 = Bits32(opcode, 14, 12);
1409
uint32_t i = Bit32(opcode, 26);
1410
uint32_t imm8 = Bits32(opcode, 7, 0);
1411
imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
1412
1413
// if BadReg(d) then UNPREDICTABLE;
1414
if (BadReg(Rd))
1415
return false;
1416
} break;
1417
1418
case eEncodingA1:
1419
// d = UInt(Rd); setflags = (S == '1'); (imm32, carry) =
1420
// ARMExpandImm_C(imm12, APSR.C);
1421
Rd = Bits32(opcode, 15, 12);
1422
setflags = BitIsSet(opcode, 20);
1423
imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
1424
1425
// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1426
// instructions;
1427
if ((Rd == 15) && setflags)
1428
return EmulateSUBSPcLrEtc(opcode, encoding);
1429
1430
break;
1431
1432
case eEncodingA2: {
1433
// d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
1434
Rd = Bits32(opcode, 15, 12);
1435
setflags = false;
1436
uint32_t imm4 = Bits32(opcode, 19, 16);
1437
uint32_t imm12 = Bits32(opcode, 11, 0);
1438
imm32 = (imm4 << 12) | imm12;
1439
1440
// if d == 15 then UNPREDICTABLE;
1441
if (Rd == 15)
1442
return false;
1443
} break;
1444
1445
default:
1446
return false;
1447
}
1448
uint32_t result = imm32;
1449
1450
// The context specifies that an immediate is to be moved into Rd.
1451
EmulateInstruction::Context context;
1452
context.type = EmulateInstruction::eContextImmediate;
1453
context.SetNoArgs();
1454
1455
if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1456
return false;
1457
}
1458
return true;
1459
}
1460
1461
// MUL multiplies two register values. The least significant 32 bits of the
1462
// result are written to the destination
1463
// register. These 32 bits do not depend on whether the source register values
1464
// are considered to be signed values or unsigned values.
1465
//
1466
// Optionally, it can update the condition flags based on the result. In the
1467
// Thumb instruction set, this option is limited to only a few forms of the
1468
// instruction.
1469
bool EmulateInstructionARM::EmulateMUL(const uint32_t opcode,
1470
const ARMEncoding encoding) {
1471
#if 0
1472
if ConditionPassed() then
1473
EncodingSpecificOperations();
1474
operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
1475
operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
1476
result = operand1 * operand2;
1477
R[d] = result<31:0>;
1478
if setflags then
1479
APSR.N = result<31>;
1480
APSR.Z = IsZeroBit(result);
1481
if ArchVersion() == 4 then
1482
APSR.C = bit UNKNOWN;
1483
// else APSR.C unchanged
1484
// APSR.V always unchanged
1485
#endif
1486
1487
if (ConditionPassed(opcode)) {
1488
uint32_t d;
1489
uint32_t n;
1490
uint32_t m;
1491
bool setflags;
1492
1493
// EncodingSpecificOperations();
1494
switch (encoding) {
1495
case eEncodingT1:
1496
// d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
1497
d = Bits32(opcode, 2, 0);
1498
n = Bits32(opcode, 5, 3);
1499
m = Bits32(opcode, 2, 0);
1500
setflags = !InITBlock();
1501
1502
// if ArchVersion() < 6 && d == n then UNPREDICTABLE;
1503
if ((ArchVersion() < ARMv6) && (d == n))
1504
return false;
1505
1506
break;
1507
1508
case eEncodingT2:
1509
// d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
1510
d = Bits32(opcode, 11, 8);
1511
n = Bits32(opcode, 19, 16);
1512
m = Bits32(opcode, 3, 0);
1513
setflags = false;
1514
1515
// if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
1516
if (BadReg(d) || BadReg(n) || BadReg(m))
1517
return false;
1518
1519
break;
1520
1521
case eEncodingA1:
1522
// d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
1523
d = Bits32(opcode, 19, 16);
1524
n = Bits32(opcode, 3, 0);
1525
m = Bits32(opcode, 11, 8);
1526
setflags = BitIsSet(opcode, 20);
1527
1528
// if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
1529
if ((d == 15) || (n == 15) || (m == 15))
1530
return false;
1531
1532
// if ArchVersion() < 6 && d == n then UNPREDICTABLE;
1533
if ((ArchVersion() < ARMv6) && (d == n))
1534
return false;
1535
1536
break;
1537
1538
default:
1539
return false;
1540
}
1541
1542
bool success = false;
1543
1544
// operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final
1545
// results
1546
uint64_t operand1 =
1547
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1548
if (!success)
1549
return false;
1550
1551
// operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final
1552
// results
1553
uint64_t operand2 =
1554
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
1555
if (!success)
1556
return false;
1557
1558
// result = operand1 * operand2;
1559
uint64_t result = operand1 * operand2;
1560
1561
// R[d] = result<31:0>;
1562
std::optional<RegisterInfo> op1_reg =
1563
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
1564
std::optional<RegisterInfo> op2_reg =
1565
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
1566
1567
EmulateInstruction::Context context;
1568
context.type = eContextArithmetic;
1569
context.SetRegisterRegisterOperands(*op1_reg, *op2_reg);
1570
1571
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
1572
(0x0000ffff & result)))
1573
return false;
1574
1575
// if setflags then
1576
if (setflags) {
1577
// APSR.N = result<31>;
1578
// APSR.Z = IsZeroBit(result);
1579
m_new_inst_cpsr = m_opcode_cpsr;
1580
SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, 31));
1581
SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
1582
if (m_new_inst_cpsr != m_opcode_cpsr) {
1583
if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1584
LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
1585
return false;
1586
}
1587
1588
// if ArchVersion() == 4 then
1589
// APSR.C = bit UNKNOWN;
1590
}
1591
}
1592
return true;
1593
}
1594
1595
// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to
1596
// the destination register. It can optionally update the condition flags based
1597
// on the value.
1598
bool EmulateInstructionARM::EmulateMVNImm(const uint32_t opcode,
1599
const ARMEncoding encoding) {
1600
#if 0
1601
// ARM pseudo code...
1602
if (ConditionPassed())
1603
{
1604
EncodingSpecificOperations();
1605
result = NOT(imm32);
1606
if d == 15 then // Can only occur for ARM encoding
1607
ALUWritePC(result); // setflags is always FALSE here
1608
else
1609
R[d] = result;
1610
if setflags then
1611
APSR.N = result<31>;
1612
APSR.Z = IsZeroBit(result);
1613
APSR.C = carry;
1614
// APSR.V unchanged
1615
}
1616
#endif
1617
1618
if (ConditionPassed(opcode)) {
1619
uint32_t Rd; // the destination register
1620
uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
1621
uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
1622
bool setflags;
1623
switch (encoding) {
1624
case eEncodingT1:
1625
Rd = Bits32(opcode, 11, 8);
1626
setflags = BitIsSet(opcode, 20);
1627
imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
1628
break;
1629
case eEncodingA1:
1630
Rd = Bits32(opcode, 15, 12);
1631
setflags = BitIsSet(opcode, 20);
1632
imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
1633
1634
// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1635
// instructions;
1636
if (Rd == 15 && setflags)
1637
return EmulateSUBSPcLrEtc(opcode, encoding);
1638
break;
1639
default:
1640
return false;
1641
}
1642
uint32_t result = ~imm32;
1643
1644
// The context specifies that an immediate is to be moved into Rd.
1645
EmulateInstruction::Context context;
1646
context.type = EmulateInstruction::eContextImmediate;
1647
context.SetNoArgs();
1648
1649
if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1650
return false;
1651
}
1652
return true;
1653
}
1654
1655
// Bitwise NOT (register) writes the bitwise inverse of a register value to the
1656
// destination register. It can optionally update the condition flags based on
1657
// the result.
1658
bool EmulateInstructionARM::EmulateMVNReg(const uint32_t opcode,
1659
const ARMEncoding encoding) {
1660
#if 0
1661
// ARM pseudo code...
1662
if (ConditionPassed())
1663
{
1664
EncodingSpecificOperations();
1665
(shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
1666
result = NOT(shifted);
1667
if d == 15 then // Can only occur for ARM encoding
1668
ALUWritePC(result); // setflags is always FALSE here
1669
else
1670
R[d] = result;
1671
if setflags then
1672
APSR.N = result<31>;
1673
APSR.Z = IsZeroBit(result);
1674
APSR.C = carry;
1675
// APSR.V unchanged
1676
}
1677
#endif
1678
1679
if (ConditionPassed(opcode)) {
1680
uint32_t Rm; // the source register
1681
uint32_t Rd; // the destination register
1682
ARM_ShifterType shift_t;
1683
uint32_t shift_n; // the shift applied to the value read from Rm
1684
bool setflags;
1685
uint32_t carry; // the carry bit after the shift operation
1686
switch (encoding) {
1687
case eEncodingT1:
1688
Rd = Bits32(opcode, 2, 0);
1689
Rm = Bits32(opcode, 5, 3);
1690
setflags = !InITBlock();
1691
shift_t = SRType_LSL;
1692
shift_n = 0;
1693
if (InITBlock())
1694
return false;
1695
break;
1696
case eEncodingT2:
1697
Rd = Bits32(opcode, 11, 8);
1698
Rm = Bits32(opcode, 3, 0);
1699
setflags = BitIsSet(opcode, 20);
1700
shift_n = DecodeImmShiftThumb(opcode, shift_t);
1701
// if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
1702
if (BadReg(Rd) || BadReg(Rm))
1703
return false;
1704
break;
1705
case eEncodingA1:
1706
Rd = Bits32(opcode, 15, 12);
1707
Rm = Bits32(opcode, 3, 0);
1708
setflags = BitIsSet(opcode, 20);
1709
shift_n = DecodeImmShiftARM(opcode, shift_t);
1710
break;
1711
default:
1712
return false;
1713
}
1714
bool success = false;
1715
uint32_t value = ReadCoreReg(Rm, &success);
1716
if (!success)
1717
return false;
1718
1719
uint32_t shifted =
1720
Shift_C(value, shift_t, shift_n, APSR_C, carry, &success);
1721
if (!success)
1722
return false;
1723
uint32_t result = ~shifted;
1724
1725
// The context specifies that an immediate is to be moved into Rd.
1726
EmulateInstruction::Context context;
1727
context.type = EmulateInstruction::eContextImmediate;
1728
context.SetNoArgs();
1729
1730
if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1731
return false;
1732
}
1733
return true;
1734
}
1735
1736
// PC relative immediate load into register, possibly followed by ADD (SP plus
1737
// register).
1738
// LDR (literal)
1739
bool EmulateInstructionARM::EmulateLDRRtPCRelative(const uint32_t opcode,
1740
const ARMEncoding encoding) {
1741
#if 0
1742
// ARM pseudo code...
1743
if (ConditionPassed())
1744
{
1745
EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1746
base = Align(PC,4);
1747
address = if add then (base + imm32) else (base - imm32);
1748
data = MemU[address,4];
1749
if t == 15 then
1750
if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1751
elsif UnalignedSupport() || address<1:0> = '00' then
1752
R[t] = data;
1753
else // Can only apply before ARMv7
1754
if CurrentInstrSet() == InstrSet_ARM then
1755
R[t] = ROR(data, 8*UInt(address<1:0>));
1756
else
1757
R[t] = bits(32) UNKNOWN;
1758
}
1759
#endif
1760
1761
if (ConditionPassed(opcode)) {
1762
bool success = false;
1763
const uint32_t pc = ReadCoreReg(PC_REG, &success);
1764
if (!success)
1765
return false;
1766
1767
// PC relative immediate load context
1768
EmulateInstruction::Context context;
1769
context.type = EmulateInstruction::eContextRegisterPlusOffset;
1770
std::optional<RegisterInfo> pc_reg =
1771
GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);
1772
context.SetRegisterPlusOffset(*pc_reg, 0);
1773
1774
uint32_t Rt; // the destination register
1775
uint32_t imm32; // immediate offset from the PC
1776
bool add; // +imm32 or -imm32?
1777
addr_t base; // the base address
1778
addr_t address; // the PC relative address
1779
uint32_t data; // the literal data value from the PC relative load
1780
switch (encoding) {
1781
case eEncodingT1:
1782
Rt = Bits32(opcode, 10, 8);
1783
imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
1784
add = true;
1785
break;
1786
case eEncodingT2:
1787
Rt = Bits32(opcode, 15, 12);
1788
imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1789
add = BitIsSet(opcode, 23);
1790
if (Rt == 15 && InITBlock() && !LastInITBlock())
1791
return false;
1792
break;
1793
default:
1794
return false;
1795
}
1796
1797
base = Align(pc, 4);
1798
if (add)
1799
address = base + imm32;
1800
else
1801
address = base - imm32;
1802
1803
context.SetRegisterPlusOffset(*pc_reg, address - base);
1804
data = MemURead(context, address, 4, 0, &success);
1805
if (!success)
1806
return false;
1807
1808
if (Rt == 15) {
1809
if (Bits32(address, 1, 0) == 0) {
1810
// In ARMv5T and above, this is an interworking branch.
1811
if (!LoadWritePC(context, data))
1812
return false;
1813
} else
1814
return false;
1815
} else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) {
1816
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rt,
1817
data))
1818
return false;
1819
} else // We don't handle ARM for now.
1820
return false;
1821
}
1822
return true;
1823
}
1824
1825
// An add operation to adjust the SP.
1826
// ADD (SP plus immediate)
1827
bool EmulateInstructionARM::EmulateADDSPImm(const uint32_t opcode,
1828
const ARMEncoding encoding) {
1829
#if 0
1830
// ARM pseudo code...
1831
if (ConditionPassed())
1832
{
1833
EncodingSpecificOperations();
1834
(result, carry, overflow) = AddWithCarry(SP, imm32, '0');
1835
if d == 15 then // Can only occur for ARM encoding
1836
ALUWritePC(result); // setflags is always FALSE here
1837
else
1838
R[d] = result;
1839
if setflags then
1840
APSR.N = result<31>;
1841
APSR.Z = IsZeroBit(result);
1842
APSR.C = carry;
1843
APSR.V = overflow;
1844
}
1845
#endif
1846
1847
bool success = false;
1848
1849
if (ConditionPassed(opcode)) {
1850
const addr_t sp = ReadCoreReg(SP_REG, &success);
1851
if (!success)
1852
return false;
1853
uint32_t imm32; // the immediate operand
1854
uint32_t d;
1855
bool setflags;
1856
switch (encoding) {
1857
case eEncodingT1:
1858
// d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
1859
d = Bits32(opcode, 10, 8);
1860
imm32 = (Bits32(opcode, 7, 0) << 2);
1861
setflags = false;
1862
break;
1863
1864
case eEncodingT2:
1865
// d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
1866
d = 13;
1867
imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1868
setflags = false;
1869
break;
1870
1871
case eEncodingT3:
1872
// d = UInt(Rd); setflags = (S == "1"); imm32 =
1873
// ThumbExpandImm(i:imm3:imm8);
1874
d = Bits32(opcode, 11, 8);
1875
imm32 = ThumbExpandImm(opcode);
1876
setflags = Bit32(opcode, 20);
1877
1878
// if Rd == "1111" && S == "1" then SEE CMN (immediate);
1879
if (d == 15 && setflags == 1)
1880
return false; // CMN (immediate) not yet supported
1881
1882
// if d == 15 && S == "0" then UNPREDICTABLE;
1883
if (d == 15 && setflags == 0)
1884
return false;
1885
break;
1886
1887
case eEncodingT4: {
1888
// if Rn == '1111' then SEE ADR;
1889
// d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
1890
d = Bits32(opcode, 11, 8);
1891
setflags = false;
1892
uint32_t i = Bit32(opcode, 26);
1893
uint32_t imm3 = Bits32(opcode, 14, 12);
1894
uint32_t imm8 = Bits32(opcode, 7, 0);
1895
imm32 = (i << 11) | (imm3 << 8) | imm8;
1896
1897
// if d == 15 then UNPREDICTABLE;
1898
if (d == 15)
1899
return false;
1900
} break;
1901
1902
default:
1903
return false;
1904
}
1905
// (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
1906
AddWithCarryResult res = AddWithCarry(sp, imm32, 0);
1907
1908
EmulateInstruction::Context context;
1909
if (d == 13)
1910
context.type = EmulateInstruction::eContextAdjustStackPointer;
1911
else
1912
context.type = EmulateInstruction::eContextRegisterPlusOffset;
1913
1914
std::optional<RegisterInfo> sp_reg =
1915
GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);
1916
context.SetRegisterPlusOffset(*sp_reg, res.result - sp);
1917
1918
if (d == 15) {
1919
if (!ALUWritePC(context, res.result))
1920
return false;
1921
} else {
1922
// R[d] = result;
1923
// if setflags then
1924
// APSR.N = result<31>;
1925
// APSR.Z = IsZeroBit(result);
1926
// APSR.C = carry;
1927
// APSR.V = overflow;
1928
if (!WriteCoreRegOptionalFlags(context, res.result, d, setflags,
1929
res.carry_out, res.overflow))
1930
return false;
1931
}
1932
}
1933
return true;
1934
}
1935
1936
// An add operation to adjust the SP.
1937
// ADD (SP plus register)
1938
bool EmulateInstructionARM::EmulateADDSPRm(const uint32_t opcode,
1939
const ARMEncoding encoding) {
1940
#if 0
1941
// ARM pseudo code...
1942
if (ConditionPassed())
1943
{
1944
EncodingSpecificOperations();
1945
shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1946
(result, carry, overflow) = AddWithCarry(SP, shifted, '0');
1947
if d == 15 then
1948
ALUWritePC(result); // setflags is always FALSE here
1949
else
1950
R[d] = result;
1951
if setflags then
1952
APSR.N = result<31>;
1953
APSR.Z = IsZeroBit(result);
1954
APSR.C = carry;
1955
APSR.V = overflow;
1956
}
1957
#endif
1958
1959
bool success = false;
1960
1961
if (ConditionPassed(opcode)) {
1962
const addr_t sp = ReadCoreReg(SP_REG, &success);
1963
if (!success)
1964
return false;
1965
uint32_t Rm; // the second operand
1966
switch (encoding) {
1967
case eEncodingT2:
1968
Rm = Bits32(opcode, 6, 3);
1969
break;
1970
default:
1971
return false;
1972
}
1973
int32_t reg_value = ReadCoreReg(Rm, &success);
1974
if (!success)
1975
return false;
1976
1977
addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1978
1979
EmulateInstruction::Context context;
1980
context.type = eContextArithmetic;
1981
std::optional<RegisterInfo> sp_reg =
1982
GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);
1983
std::optional<RegisterInfo> other_reg =
1984
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);
1985
context.SetRegisterRegisterOperands(*sp_reg, *other_reg);
1986
1987
if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1988
LLDB_REGNUM_GENERIC_SP, addr))
1989
return false;
1990
}
1991
return true;
1992
}
1993
1994
// Branch with Link and Exchange Instruction Sets (immediate) calls a
1995
// subroutine at a PC-relative address, and changes instruction set from ARM to
1996
// Thumb, or from Thumb to ARM.
1997
// BLX (immediate)
1998
bool EmulateInstructionARM::EmulateBLXImmediate(const uint32_t opcode,
1999
const ARMEncoding encoding) {
2000
#if 0
2001
// ARM pseudo code...
2002
if (ConditionPassed())
2003
{
2004
EncodingSpecificOperations();
2005
if CurrentInstrSet() == InstrSet_ARM then
2006
LR = PC - 4;
2007
else
2008
LR = PC<31:1> : '1';
2009
if targetInstrSet == InstrSet_ARM then
2010
targetAddress = Align(PC,4) + imm32;
2011
else
2012
targetAddress = PC + imm32;
2013
SelectInstrSet(targetInstrSet);
2014
BranchWritePC(targetAddress);
2015
}
2016
#endif
2017
2018
bool success = true;
2019
2020
if (ConditionPassed(opcode)) {
2021
EmulateInstruction::Context context;
2022
context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2023
const uint32_t pc = ReadCoreReg(PC_REG, &success);
2024
if (!success)
2025
return false;
2026
addr_t lr; // next instruction address
2027
addr_t target; // target address
2028
int32_t imm32; // PC-relative offset
2029
switch (encoding) {
2030
case eEncodingT1: {
2031
lr = pc | 1u; // return address
2032
uint32_t S = Bit32(opcode, 26);
2033
uint32_t imm10 = Bits32(opcode, 25, 16);
2034
uint32_t J1 = Bit32(opcode, 13);
2035
uint32_t J2 = Bit32(opcode, 11);
2036
uint32_t imm11 = Bits32(opcode, 10, 0);
2037
uint32_t I1 = !(J1 ^ S);
2038
uint32_t I2 = !(J2 ^ S);
2039
uint32_t imm25 =
2040
(S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
2041
imm32 = llvm::SignExtend32<25>(imm25);
2042
target = pc + imm32;
2043
SelectInstrSet(eModeThumb);
2044
context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2045
if (InITBlock() && !LastInITBlock())
2046
return false;
2047
break;
2048
}
2049
case eEncodingT2: {
2050
lr = pc | 1u; // return address
2051
uint32_t S = Bit32(opcode, 26);
2052
uint32_t imm10H = Bits32(opcode, 25, 16);
2053
uint32_t J1 = Bit32(opcode, 13);
2054
uint32_t J2 = Bit32(opcode, 11);
2055
uint32_t imm10L = Bits32(opcode, 10, 1);
2056
uint32_t I1 = !(J1 ^ S);
2057
uint32_t I2 = !(J2 ^ S);
2058
uint32_t imm25 =
2059
(S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
2060
imm32 = llvm::SignExtend32<25>(imm25);
2061
target = Align(pc, 4) + imm32;
2062
SelectInstrSet(eModeARM);
2063
context.SetISAAndImmediateSigned(eModeARM, 4 + imm32);
2064
if (InITBlock() && !LastInITBlock())
2065
return false;
2066
break;
2067
}
2068
case eEncodingA1:
2069
lr = pc - 4; // return address
2070
imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
2071
target = Align(pc, 4) + imm32;
2072
SelectInstrSet(eModeARM);
2073
context.SetISAAndImmediateSigned(eModeARM, 8 + imm32);
2074
break;
2075
case eEncodingA2:
2076
lr = pc - 4; // return address
2077
imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 |
2078
Bits32(opcode, 24, 24) << 1);
2079
target = pc + imm32;
2080
SelectInstrSet(eModeThumb);
2081
context.SetISAAndImmediateSigned(eModeThumb, 8 + imm32);
2082
break;
2083
default:
2084
return false;
2085
}
2086
if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2087
LLDB_REGNUM_GENERIC_RA, lr))
2088
return false;
2089
if (!BranchWritePC(context, target))
2090
return false;
2091
if (m_opcode_cpsr != m_new_inst_cpsr)
2092
if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2093
LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2094
return false;
2095
}
2096
return true;
2097
}
2098
2099
// Branch with Link and Exchange (register) calls a subroutine at an address
2100
// and instruction set specified by a register.
2101
// BLX (register)
2102
bool EmulateInstructionARM::EmulateBLXRm(const uint32_t opcode,
2103
const ARMEncoding encoding) {
2104
#if 0
2105
// ARM pseudo code...
2106
if (ConditionPassed())
2107
{
2108
EncodingSpecificOperations();
2109
target = R[m];
2110
if CurrentInstrSet() == InstrSet_ARM then
2111
next_instr_addr = PC - 4;
2112
LR = next_instr_addr;
2113
else
2114
next_instr_addr = PC - 2;
2115
LR = next_instr_addr<31:1> : '1';
2116
BXWritePC(target);
2117
}
2118
#endif
2119
2120
bool success = false;
2121
2122
if (ConditionPassed(opcode)) {
2123
EmulateInstruction::Context context;
2124
context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
2125
const uint32_t pc = ReadCoreReg(PC_REG, &success);
2126
addr_t lr; // next instruction address
2127
if (!success)
2128
return false;
2129
uint32_t Rm; // the register with the target address
2130
switch (encoding) {
2131
case eEncodingT1:
2132
lr = (pc - 2) | 1u; // return address
2133
Rm = Bits32(opcode, 6, 3);
2134
// if m == 15 then UNPREDICTABLE;
2135
if (Rm == 15)
2136
return false;
2137
if (InITBlock() && !LastInITBlock())
2138
return false;
2139
break;
2140
case eEncodingA1:
2141
lr = pc - 4; // return address
2142
Rm = Bits32(opcode, 3, 0);
2143
// if m == 15 then UNPREDICTABLE;
2144
if (Rm == 15)
2145
return false;
2146
break;
2147
default:
2148
return false;
2149
}
2150
addr_t target = ReadCoreReg(Rm, &success);
2151
if (!success)
2152
return false;
2153
std::optional<RegisterInfo> dwarf_reg =
2154
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);
2155
context.SetRegister(*dwarf_reg);
2156
if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2157
LLDB_REGNUM_GENERIC_RA, lr))
2158
return false;
2159
if (!BXWritePC(context, target))
2160
return false;
2161
}
2162
return true;
2163
}
2164
2165
// Branch and Exchange causes a branch to an address and instruction set
2166
// specified by a register.
2167
bool EmulateInstructionARM::EmulateBXRm(const uint32_t opcode,
2168
const ARMEncoding encoding) {
2169
#if 0
2170
// ARM pseudo code...
2171
if (ConditionPassed())
2172
{
2173
EncodingSpecificOperations();
2174
BXWritePC(R[m]);
2175
}
2176
#endif
2177
2178
if (ConditionPassed(opcode)) {
2179
EmulateInstruction::Context context;
2180
context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
2181
uint32_t Rm; // the register with the target address
2182
switch (encoding) {
2183
case eEncodingT1:
2184
Rm = Bits32(opcode, 6, 3);
2185
if (InITBlock() && !LastInITBlock())
2186
return false;
2187
break;
2188
case eEncodingA1:
2189
Rm = Bits32(opcode, 3, 0);
2190
break;
2191
default:
2192
return false;
2193
}
2194
bool success = false;
2195
addr_t target = ReadCoreReg(Rm, &success);
2196
if (!success)
2197
return false;
2198
2199
std::optional<RegisterInfo> dwarf_reg =
2200
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);
2201
context.SetRegister(*dwarf_reg);
2202
if (!BXWritePC(context, target))
2203
return false;
2204
}
2205
return true;
2206
}
2207
2208
// Branch and Exchange Jazelle attempts to change to Jazelle state. If the
2209
// attempt fails, it branches to an address and instruction set specified by a
2210
// register as though it were a BX instruction.
2211
//
2212
// TODO: Emulate Jazelle architecture?
2213
// We currently assume that switching to Jazelle state fails, thus
2214
// treating BXJ as a BX operation.
2215
bool EmulateInstructionARM::EmulateBXJRm(const uint32_t opcode,
2216
const ARMEncoding encoding) {
2217
#if 0
2218
// ARM pseudo code...
2219
if (ConditionPassed())
2220
{
2221
EncodingSpecificOperations();
2222
if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
2223
BXWritePC(R[m]);
2224
else
2225
if JazelleAcceptsExecution() then
2226
SwitchToJazelleExecution();
2227
else
2228
SUBARCHITECTURE_DEFINED handler call;
2229
}
2230
#endif
2231
2232
if (ConditionPassed(opcode)) {
2233
EmulateInstruction::Context context;
2234
context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
2235
uint32_t Rm; // the register with the target address
2236
switch (encoding) {
2237
case eEncodingT1:
2238
Rm = Bits32(opcode, 19, 16);
2239
if (BadReg(Rm))
2240
return false;
2241
if (InITBlock() && !LastInITBlock())
2242
return false;
2243
break;
2244
case eEncodingA1:
2245
Rm = Bits32(opcode, 3, 0);
2246
if (Rm == 15)
2247
return false;
2248
break;
2249
default:
2250
return false;
2251
}
2252
bool success = false;
2253
addr_t target = ReadCoreReg(Rm, &success);
2254
if (!success)
2255
return false;
2256
2257
std::optional<RegisterInfo> dwarf_reg =
2258
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);
2259
context.SetRegister(*dwarf_reg);
2260
if (!BXWritePC(context, target))
2261
return false;
2262
}
2263
return true;
2264
}
2265
2266
// Set r7 to point to some ip offset.
2267
// SUB (immediate)
2268
bool EmulateInstructionARM::EmulateSUBR7IPImm(const uint32_t opcode,
2269
const ARMEncoding encoding) {
2270
#if 0
2271
// ARM pseudo code...
2272
if (ConditionPassed())
2273
{
2274
EncodingSpecificOperations();
2275
(result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
2276
if d == 15 then // Can only occur for ARM encoding
2277
ALUWritePC(result); // setflags is always FALSE here
2278
else
2279
R[d] = result;
2280
if setflags then
2281
APSR.N = result<31>;
2282
APSR.Z = IsZeroBit(result);
2283
APSR.C = carry;
2284
APSR.V = overflow;
2285
}
2286
#endif
2287
2288
if (ConditionPassed(opcode)) {
2289
bool success = false;
2290
const addr_t ip = ReadCoreReg(12, &success);
2291
if (!success)
2292
return false;
2293
uint32_t imm32;
2294
switch (encoding) {
2295
case eEncodingA1:
2296
imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2297
break;
2298
default:
2299
return false;
2300
}
2301
addr_t ip_offset = imm32;
2302
addr_t addr = ip - ip_offset; // the adjusted ip value
2303
2304
EmulateInstruction::Context context;
2305
context.type = EmulateInstruction::eContextRegisterPlusOffset;
2306
std::optional<RegisterInfo> dwarf_reg =
2307
GetRegisterInfo(eRegisterKindDWARF, dwarf_r12);
2308
context.SetRegisterPlusOffset(*dwarf_reg, -ip_offset);
2309
2310
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r7, addr))
2311
return false;
2312
}
2313
return true;
2314
}
2315
2316
// Set ip to point to some stack offset.
2317
// SUB (SP minus immediate)
2318
bool EmulateInstructionARM::EmulateSUBIPSPImm(const uint32_t opcode,
2319
const ARMEncoding encoding) {
2320
#if 0
2321
// ARM pseudo code...
2322
if (ConditionPassed())
2323
{
2324
EncodingSpecificOperations();
2325
(result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
2326
if d == 15 then // Can only occur for ARM encoding
2327
ALUWritePC(result); // setflags is always FALSE here
2328
else
2329
R[d] = result;
2330
if setflags then
2331
APSR.N = result<31>;
2332
APSR.Z = IsZeroBit(result);
2333
APSR.C = carry;
2334
APSR.V = overflow;
2335
}
2336
#endif
2337
2338
if (ConditionPassed(opcode)) {
2339
bool success = false;
2340
const addr_t sp = ReadCoreReg(SP_REG, &success);
2341
if (!success)
2342
return false;
2343
uint32_t imm32;
2344
switch (encoding) {
2345
case eEncodingA1:
2346
imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2347
break;
2348
default:
2349
return false;
2350
}
2351
addr_t sp_offset = imm32;
2352
addr_t addr = sp - sp_offset; // the adjusted stack pointer value
2353
2354
EmulateInstruction::Context context;
2355
context.type = EmulateInstruction::eContextRegisterPlusOffset;
2356
std::optional<RegisterInfo> dwarf_reg =
2357
GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
2358
context.SetRegisterPlusOffset(*dwarf_reg, -sp_offset);
2359
2360
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r12, addr))
2361
return false;
2362
}
2363
return true;
2364
}
2365
2366
// This instruction subtracts an immediate value from the SP value, and writes
2367
// the result to the destination register.
2368
//
2369
// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local
2370
// storage.
2371
bool EmulateInstructionARM::EmulateSUBSPImm(const uint32_t opcode,
2372
const ARMEncoding encoding) {
2373
#if 0
2374
// ARM pseudo code...
2375
if (ConditionPassed())
2376
{
2377
EncodingSpecificOperations();
2378
(result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
2379
if d == 15 then // Can only occur for ARM encoding
2380
ALUWritePC(result); // setflags is always FALSE here
2381
else
2382
R[d] = result;
2383
if setflags then
2384
APSR.N = result<31>;
2385
APSR.Z = IsZeroBit(result);
2386
APSR.C = carry;
2387
APSR.V = overflow;
2388
}
2389
#endif
2390
2391
bool success = false;
2392
if (ConditionPassed(opcode)) {
2393
const addr_t sp = ReadCoreReg(SP_REG, &success);
2394
if (!success)
2395
return false;
2396
2397
uint32_t Rd;
2398
bool setflags;
2399
uint32_t imm32;
2400
switch (encoding) {
2401
case eEncodingT1:
2402
Rd = 13;
2403
setflags = false;
2404
imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
2405
break;
2406
case eEncodingT2:
2407
Rd = Bits32(opcode, 11, 8);
2408
setflags = BitIsSet(opcode, 20);
2409
imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2410
if (Rd == 15 && setflags)
2411
return EmulateCMPImm(opcode, eEncodingT2);
2412
if (Rd == 15 && !setflags)
2413
return false;
2414
break;
2415
case eEncodingT3:
2416
Rd = Bits32(opcode, 11, 8);
2417
setflags = false;
2418
imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
2419
if (Rd == 15)
2420
return false;
2421
break;
2422
case eEncodingA1:
2423
Rd = Bits32(opcode, 15, 12);
2424
setflags = BitIsSet(opcode, 20);
2425
imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2426
2427
// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
2428
// instructions;
2429
if (Rd == 15 && setflags)
2430
return EmulateSUBSPcLrEtc(opcode, encoding);
2431
break;
2432
default:
2433
return false;
2434
}
2435
AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
2436
2437
EmulateInstruction::Context context;
2438
if (Rd == 13) {
2439
uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting
2440
// to negate it, or the wrong
2441
// value gets passed down to context.SetImmediateSigned.
2442
context.type = EmulateInstruction::eContextAdjustStackPointer;
2443
context.SetImmediateSigned(-imm64); // the stack pointer offset
2444
} else {
2445
context.type = EmulateInstruction::eContextImmediate;
2446
context.SetNoArgs();
2447
}
2448
2449
if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
2450
res.carry_out, res.overflow))
2451
return false;
2452
}
2453
return true;
2454
}
2455
2456
// A store operation to the stack that also updates the SP.
2457
bool EmulateInstructionARM::EmulateSTRRtSP(const uint32_t opcode,
2458
const ARMEncoding encoding) {
2459
#if 0
2460
// ARM pseudo code...
2461
if (ConditionPassed())
2462
{
2463
EncodingSpecificOperations();
2464
offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
2465
address = if index then offset_addr else R[n];
2466
MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
2467
if wback then R[n] = offset_addr;
2468
}
2469
#endif
2470
2471
bool success = false;
2472
if (ConditionPassed(opcode)) {
2473
const uint32_t addr_byte_size = GetAddressByteSize();
2474
const addr_t sp = ReadCoreReg(SP_REG, &success);
2475
if (!success)
2476
return false;
2477
uint32_t Rt; // the source register
2478
uint32_t imm12;
2479
uint32_t
2480
Rn; // This function assumes Rn is the SP, but we should verify that.
2481
2482
bool index;
2483
bool add;
2484
bool wback;
2485
switch (encoding) {
2486
case eEncodingA1:
2487
Rt = Bits32(opcode, 15, 12);
2488
imm12 = Bits32(opcode, 11, 0);
2489
Rn = Bits32(opcode, 19, 16);
2490
2491
if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
2492
return false;
2493
2494
index = BitIsSet(opcode, 24);
2495
add = BitIsSet(opcode, 23);
2496
wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
2497
2498
if (wback && ((Rn == 15) || (Rn == Rt)))
2499
return false;
2500
break;
2501
default:
2502
return false;
2503
}
2504
addr_t offset_addr;
2505
if (add)
2506
offset_addr = sp + imm12;
2507
else
2508
offset_addr = sp - imm12;
2509
2510
addr_t addr;
2511
if (index)
2512
addr = offset_addr;
2513
else
2514
addr = sp;
2515
2516
EmulateInstruction::Context context;
2517
context.type = EmulateInstruction::eContextPushRegisterOnStack;
2518
std::optional<RegisterInfo> sp_reg =
2519
GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);
2520
std::optional<RegisterInfo> dwarf_reg =
2521
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rt);
2522
2523
context.SetRegisterToRegisterPlusOffset(*dwarf_reg, *sp_reg, addr - sp);
2524
if (Rt != 15) {
2525
uint32_t reg_value = ReadCoreReg(Rt, &success);
2526
if (!success)
2527
return false;
2528
if (!MemUWrite(context, addr, reg_value, addr_byte_size))
2529
return false;
2530
} else {
2531
const uint32_t pc = ReadCoreReg(PC_REG, &success);
2532
if (!success)
2533
return false;
2534
if (!MemUWrite(context, addr, pc, addr_byte_size))
2535
return false;
2536
}
2537
2538
if (wback) {
2539
context.type = EmulateInstruction::eContextAdjustStackPointer;
2540
context.SetImmediateSigned(addr - sp);
2541
if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2542
LLDB_REGNUM_GENERIC_SP, offset_addr))
2543
return false;
2544
}
2545
}
2546
return true;
2547
}
2548
2549
// Vector Push stores multiple extension registers to the stack. It also
2550
// updates SP to point to the start of the stored data.
2551
bool EmulateInstructionARM::EmulateVPUSH(const uint32_t opcode,
2552
const ARMEncoding encoding) {
2553
#if 0
2554
// ARM pseudo code...
2555
if (ConditionPassed())
2556
{
2557
EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2558
address = SP - imm32;
2559
SP = SP - imm32;
2560
if single_regs then
2561
for r = 0 to regs-1
2562
MemA[address,4] = S[d+r]; address = address+4;
2563
else
2564
for r = 0 to regs-1
2565
// Store as two word-aligned words in the correct order for
2566
// current endianness.
2567
MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
2568
MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
2569
address = address+8;
2570
}
2571
#endif
2572
2573
bool success = false;
2574
if (ConditionPassed(opcode)) {
2575
const uint32_t addr_byte_size = GetAddressByteSize();
2576
const addr_t sp = ReadCoreReg(SP_REG, &success);
2577
if (!success)
2578
return false;
2579
bool single_regs;
2580
uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2581
uint32_t imm32; // stack offset
2582
uint32_t regs; // number of registers
2583
switch (encoding) {
2584
case eEncodingT1:
2585
case eEncodingA1:
2586
single_regs = false;
2587
d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
2588
imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2589
// If UInt(imm8) is odd, see "FSTMX".
2590
regs = Bits32(opcode, 7, 0) / 2;
2591
// if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2592
if (regs == 0 || regs > 16 || (d + regs) > 32)
2593
return false;
2594
break;
2595
case eEncodingT2:
2596
case eEncodingA2:
2597
single_regs = true;
2598
d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
2599
imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2600
regs = Bits32(opcode, 7, 0);
2601
// if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2602
if (regs == 0 || regs > 16 || (d + regs) > 32)
2603
return false;
2604
break;
2605
default:
2606
return false;
2607
}
2608
uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2609
uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2610
addr_t sp_offset = imm32;
2611
addr_t addr = sp - sp_offset;
2612
uint32_t i;
2613
2614
EmulateInstruction::Context context;
2615
context.type = EmulateInstruction::eContextPushRegisterOnStack;
2616
2617
std::optional<RegisterInfo> sp_reg =
2618
GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);
2619
for (i = 0; i < regs; ++i) {
2620
std::optional<RegisterInfo> dwarf_reg =
2621
GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i);
2622
context.SetRegisterToRegisterPlusOffset(*dwarf_reg, *sp_reg, addr - sp);
2623
// uint64_t to accommodate 64-bit registers.
2624
uint64_t reg_value = ReadRegisterUnsigned(*dwarf_reg, 0, &success);
2625
if (!success)
2626
return false;
2627
if (!MemAWrite(context, addr, reg_value, reg_byte_size))
2628
return false;
2629
addr += reg_byte_size;
2630
}
2631
2632
context.type = EmulateInstruction::eContextAdjustStackPointer;
2633
context.SetImmediateSigned(-sp_offset);
2634
2635
if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2636
LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
2637
return false;
2638
}
2639
return true;
2640
}
2641
2642
// Vector Pop loads multiple extension registers from the stack. It also
2643
// updates SP to point just above the loaded data.
2644
bool EmulateInstructionARM::EmulateVPOP(const uint32_t opcode,
2645
const ARMEncoding encoding) {
2646
#if 0
2647
// ARM pseudo code...
2648
if (ConditionPassed())
2649
{
2650
EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2651
address = SP;
2652
SP = SP + imm32;
2653
if single_regs then
2654
for r = 0 to regs-1
2655
S[d+r] = MemA[address,4]; address = address+4;
2656
else
2657
for r = 0 to regs-1
2658
word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
2659
// Combine the word-aligned words in the correct order for
2660
// current endianness.
2661
D[d+r] = if BigEndian() then word1:word2 else word2:word1;
2662
}
2663
#endif
2664
2665
bool success = false;
2666
if (ConditionPassed(opcode)) {
2667
const uint32_t addr_byte_size = GetAddressByteSize();
2668
const addr_t sp = ReadCoreReg(SP_REG, &success);
2669
if (!success)
2670
return false;
2671
bool single_regs;
2672
uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2673
uint32_t imm32; // stack offset
2674
uint32_t regs; // number of registers
2675
switch (encoding) {
2676
case eEncodingT1:
2677
case eEncodingA1:
2678
single_regs = false;
2679
d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
2680
imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2681
// If UInt(imm8) is odd, see "FLDMX".
2682
regs = Bits32(opcode, 7, 0) / 2;
2683
// if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2684
if (regs == 0 || regs > 16 || (d + regs) > 32)
2685
return false;
2686
break;
2687
case eEncodingT2:
2688
case eEncodingA2:
2689
single_regs = true;
2690
d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
2691
imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2692
regs = Bits32(opcode, 7, 0);
2693
// if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2694
if (regs == 0 || regs > 16 || (d + regs) > 32)
2695
return false;
2696
break;
2697
default:
2698
return false;
2699
}
2700
uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2701
uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2702
addr_t sp_offset = imm32;
2703
addr_t addr = sp;
2704
uint32_t i;
2705
uint64_t data; // uint64_t to accommodate 64-bit registers.
2706
2707
EmulateInstruction::Context context;
2708
context.type = EmulateInstruction::eContextPopRegisterOffStack;
2709
2710
for (i = 0; i < regs; ++i) {
2711
std::optional<RegisterInfo> dwarf_reg =
2712
GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i);
2713
context.SetAddress(addr);
2714
data = MemARead(context, addr, reg_byte_size, 0, &success);
2715
if (!success)
2716
return false;
2717
if (!WriteRegisterUnsigned(context, *dwarf_reg, data))
2718
return false;
2719
addr += reg_byte_size;
2720
}
2721
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)
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.
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
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.
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
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
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.
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
std::optional<RegisterInfo> reg_n =
3110
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
3111
EmulateInstruction::Context context;
3112
context.type = eContextArithmetic;
3113
context.SetRegisterPlusOffset(*reg_n, imm32);
3114
3115
// R[d] = result;
3116
// if setflags then
3117
// APSR.N = result<31>;
3118
// APSR.Z = IsZeroBit(result);
3119
// APSR.C = carry;
3120
// APSR.V = overflow;
3121
if (!WriteCoreRegOptionalFlags(context, res.result, d, setflags,
3122
res.carry_out, res.overflow))
3123
return false;
3124
}
3125
return true;
3126
}
3127
3128
// This instruction adds an immediate value to a register value, and writes the
3129
// result to the destination register. It can optionally update the condition
3130
// flags based on the result.
3131
bool EmulateInstructionARM::EmulateADDImmARM(const uint32_t opcode,
3132
const ARMEncoding encoding) {
3133
#if 0
3134
// ARM pseudo code...
3135
if ConditionPassed() then
3136
EncodingSpecificOperations();
3137
(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3138
if d == 15 then
3139
ALUWritePC(result); // setflags is always FALSE here
3140
else
3141
R[d] = result;
3142
if setflags then
3143
APSR.N = result<31>;
3144
APSR.Z = IsZeroBit(result);
3145
APSR.C = carry;
3146
APSR.V = overflow;
3147
#endif
3148
3149
bool success = false;
3150
3151
if (ConditionPassed(opcode)) {
3152
uint32_t Rd, Rn;
3153
uint32_t
3154
imm32; // the immediate value to be added to the value obtained from Rn
3155
bool setflags;
3156
switch (encoding) {
3157
case eEncodingA1:
3158
Rd = Bits32(opcode, 15, 12);
3159
Rn = Bits32(opcode, 19, 16);
3160
setflags = BitIsSet(opcode, 20);
3161
imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3162
break;
3163
default:
3164
return false;
3165
}
3166
3167
// Read the first operand.
3168
uint32_t val1 = ReadCoreReg(Rn, &success);
3169
if (!success)
3170
return false;
3171
3172
AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
3173
3174
EmulateInstruction::Context context;
3175
if (Rd == 13)
3176
context.type = EmulateInstruction::eContextAdjustStackPointer;
3177
else if (Rd == GetFramePointerRegisterNumber())
3178
context.type = EmulateInstruction::eContextSetFramePointer;
3179
else
3180
context.type = EmulateInstruction::eContextRegisterPlusOffset;
3181
3182
std::optional<RegisterInfo> dwarf_reg =
3183
GetRegisterInfo(eRegisterKindDWARF, Rn);
3184
context.SetRegisterPlusOffset(*dwarf_reg, imm32);
3185
3186
if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
3187
res.carry_out, res.overflow))
3188
return false;
3189
}
3190
return true;
3191
}
3192
3193
// This instruction adds a register value and an optionally-shifted register
3194
// value, and writes the result to the destination register. It can optionally
3195
// update the condition flags based on the result.
3196
bool EmulateInstructionARM::EmulateADDReg(const uint32_t opcode,
3197
const ARMEncoding encoding) {
3198
#if 0
3199
// ARM pseudo code...
3200
if ConditionPassed() then
3201
EncodingSpecificOperations();
3202
shifted = Shift(R[m], shift_t, shift_n, APSR.C);
3203
(result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
3204
if d == 15 then
3205
ALUWritePC(result); // setflags is always FALSE here
3206
else
3207
R[d] = result;
3208
if setflags then
3209
APSR.N = result<31>;
3210
APSR.Z = IsZeroBit(result);
3211
APSR.C = carry;
3212
APSR.V = overflow;
3213
#endif
3214
3215
bool success = false;
3216
3217
if (ConditionPassed(opcode)) {
3218
uint32_t Rd, Rn, Rm;
3219
ARM_ShifterType shift_t;
3220
uint32_t shift_n; // the shift applied to the value read from Rm
3221
bool setflags;
3222
switch (encoding) {
3223
case eEncodingT1:
3224
Rd = Bits32(opcode, 2, 0);
3225
Rn = Bits32(opcode, 5, 3);
3226
Rm = Bits32(opcode, 8, 6);
3227
setflags = !InITBlock();
3228
shift_t = SRType_LSL;
3229
shift_n = 0;
3230
break;
3231
case eEncodingT2:
3232
Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
3233
Rm = Bits32(opcode, 6, 3);
3234
setflags = false;
3235
shift_t = SRType_LSL;
3236
shift_n = 0;
3237
if (Rn == 15 && Rm == 15)
3238
return false;
3239
if (Rd == 15 && InITBlock() && !LastInITBlock())
3240
return false;
3241
break;
3242
case eEncodingA1:
3243
Rd = Bits32(opcode, 15, 12);
3244
Rn = Bits32(opcode, 19, 16);
3245
Rm = Bits32(opcode, 3, 0);
3246
setflags = BitIsSet(opcode, 20);
3247
shift_n = DecodeImmShiftARM(opcode, shift_t);
3248
break;
3249
default:
3250
return false;
3251
}
3252
3253
// Read the first operand.
3254
uint32_t val1 = ReadCoreReg(Rn, &success);
3255
if (!success)
3256
return false;
3257
3258
// Read the second operand.
3259
uint32_t val2 = ReadCoreReg(Rm, &success);
3260
if (!success)
3261
return false;
3262
3263
uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
3264
if (!success)
3265
return false;
3266
AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
3267
3268
EmulateInstruction::Context context;
3269
context.type = eContextArithmetic;
3270
std::optional<RegisterInfo> op1_reg =
3271
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn);
3272
std::optional<RegisterInfo> op2_reg =
3273
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);
3274
context.SetRegisterRegisterOperands(*op1_reg, *op2_reg);
3275
3276
if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
3277
res.carry_out, res.overflow))
3278
return false;
3279
}
3280
return true;
3281
}
3282
3283
// Compare Negative (immediate) adds a register value and an immediate value.
3284
// It updates the condition flags based on the result, and discards the result.
3285
bool EmulateInstructionARM::EmulateCMNImm(const uint32_t opcode,
3286
const ARMEncoding encoding) {
3287
#if 0
3288
// ARM pseudo code...
3289
if ConditionPassed() then
3290
EncodingSpecificOperations();
3291
(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3292
APSR.N = result<31>;
3293
APSR.Z = IsZeroBit(result);
3294
APSR.C = carry;
3295
APSR.V = overflow;
3296
#endif
3297
3298
bool success = false;
3299
3300
uint32_t Rn; // the first operand
3301
uint32_t imm32; // the immediate value to be compared with
3302
switch (encoding) {
3303
case eEncodingT1:
3304
Rn = Bits32(opcode, 19, 16);
3305
imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
3306
if (Rn == 15)
3307
return false;
3308
break;
3309
case eEncodingA1:
3310
Rn = Bits32(opcode, 19, 16);
3311
imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3312
break;
3313
default:
3314
return false;
3315
}
3316
// Read the register value from the operand register Rn.
3317
uint32_t reg_val = ReadCoreReg(Rn, &success);
3318
if (!success)
3319
return false;
3320
3321
AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
3322
3323
EmulateInstruction::Context context;
3324
context.type = EmulateInstruction::eContextImmediate;
3325
context.SetNoArgs();
3326
return WriteFlags(context, res.result, res.carry_out, res.overflow);
3327
}
3328
3329
// Compare Negative (register) adds a register value and an optionally-shifted
3330
// register value. It updates the condition flags based on the result, and
3331
// discards the result.
3332
bool EmulateInstructionARM::EmulateCMNReg(const uint32_t opcode,
3333
const ARMEncoding encoding) {
3334
#if 0
3335
// ARM pseudo code...
3336
if ConditionPassed() then
3337
EncodingSpecificOperations();
3338
shifted = Shift(R[m], shift_t, shift_n, APSR.C);
3339
(result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
3340
APSR.N = result<31>;
3341
APSR.Z = IsZeroBit(result);
3342
APSR.C = carry;
3343
APSR.V = overflow;
3344
#endif
3345
3346
bool success = false;
3347
3348
uint32_t Rn; // the first operand
3349
uint32_t Rm; // the second operand
3350
ARM_ShifterType shift_t;
3351
uint32_t shift_n; // the shift applied to the value read from Rm
3352
switch (encoding) {
3353
case eEncodingT1:
3354
Rn = Bits32(opcode, 2, 0);
3355
Rm = Bits32(opcode, 5, 3);
3356
shift_t = SRType_LSL;
3357
shift_n = 0;
3358
break;
3359
case eEncodingT2:
3360
Rn = Bits32(opcode, 19, 16);
3361
Rm = Bits32(opcode, 3, 0);
3362
shift_n = DecodeImmShiftThumb(opcode, shift_t);
3363
// if n == 15 || BadReg(m) then UNPREDICTABLE;
3364
if (Rn == 15 || BadReg(Rm))
3365
return false;
3366
break;
3367
case eEncodingA1:
3368
Rn = Bits32(opcode, 19, 16);
3369
Rm = Bits32(opcode, 3, 0);
3370
shift_n = DecodeImmShiftARM(opcode, shift_t);
3371
break;
3372
default:
3373
return false;
3374
}
3375
// Read the register value from register Rn.
3376
uint32_t val1 = ReadCoreReg(Rn, &success);
3377
if (!success)
3378
return false;
3379
3380
// Read the register value from register Rm.
3381
uint32_t val2 = ReadCoreReg(Rm, &success);
3382
if (!success)
3383
return false;
3384
3385
uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
3386
if (!success)
3387
return false;
3388
AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
3389
3390
EmulateInstruction::Context context;
3391
context.type = EmulateInstruction::eContextImmediate;
3392
context.SetNoArgs();
3393
return WriteFlags(context, res.result, res.carry_out, res.overflow);
3394
}
3395
3396
// Compare (immediate) subtracts an immediate value from a register value. It
3397
// updates the condition flags based on the result, and discards the result.
3398
bool EmulateInstructionARM::EmulateCMPImm(const uint32_t opcode,
3399
const ARMEncoding encoding) {
3400
#if 0
3401
// ARM pseudo code...
3402
if ConditionPassed() then
3403
EncodingSpecificOperations();
3404
(result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
3405
APSR.N = result<31>;
3406
APSR.Z = IsZeroBit(result);
3407
APSR.C = carry;
3408
APSR.V = overflow;
3409
#endif
3410
3411
bool success = false;
3412
3413
uint32_t Rn; // the first operand
3414
uint32_t imm32; // the immediate value to be compared with
3415
switch (encoding) {
3416
case eEncodingT1:
3417
Rn = Bits32(opcode, 10, 8);
3418
imm32 = Bits32(opcode, 7, 0);
3419
break;
3420
case eEncodingT2:
3421
Rn = Bits32(opcode, 19, 16);
3422
imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
3423
if (Rn == 15)
3424
return false;
3425
break;
3426
case eEncodingA1:
3427
Rn = Bits32(opcode, 19, 16);
3428
imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3429
break;
3430
default:
3431
return false;
3432
}
3433
// Read the register value from the operand register Rn.
3434
uint32_t reg_val = ReadCoreReg(Rn, &success);
3435
if (!success)
3436
return false;
3437
3438
AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
3439
3440
EmulateInstruction::Context context;
3441
context.type = EmulateInstruction::eContextImmediate;
3442
context.SetNoArgs();
3443
return WriteFlags(context, res.result, res.carry_out, res.overflow);
3444
}
3445
3446
// Compare (register) subtracts an optionally-shifted register value from a
3447
// register value. It updates the condition flags based on the result, and
3448
// discards the result.
3449
bool EmulateInstructionARM::EmulateCMPReg(const uint32_t opcode,
3450
const ARMEncoding encoding) {
3451
#if 0
3452
// ARM pseudo code...
3453
if ConditionPassed() then
3454
EncodingSpecificOperations();
3455
shifted = Shift(R[m], shift_t, shift_n, APSR.C);
3456
(result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
3457
APSR.N = result<31>;
3458
APSR.Z = IsZeroBit(result);
3459
APSR.C = carry;
3460
APSR.V = overflow;
3461
#endif
3462
3463
bool success = false;
3464
3465
uint32_t Rn; // the first operand
3466
uint32_t Rm; // the second operand
3467
ARM_ShifterType shift_t;
3468
uint32_t shift_n; // the shift applied to the value read from Rm
3469
switch (encoding) {
3470
case eEncodingT1:
3471
Rn = Bits32(opcode, 2, 0);
3472
Rm = Bits32(opcode, 5, 3);
3473
shift_t = SRType_LSL;
3474
shift_n = 0;
3475
break;
3476
case eEncodingT2:
3477
Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
3478
Rm = Bits32(opcode, 6, 3);
3479
shift_t = SRType_LSL;
3480
shift_n = 0;
3481
if (Rn < 8 && Rm < 8)
3482
return false;
3483
if (Rn == 15 || Rm == 15)
3484
return false;
3485
break;
3486
case eEncodingT3:
3487
Rn = Bits32(opcode, 19, 16);
3488
Rm = Bits32(opcode, 3, 0);
3489
shift_n = DecodeImmShiftThumb(opcode, shift_t);
3490
if (Rn == 15 || BadReg(Rm))
3491
return false;
3492
break;
3493
case eEncodingA1:
3494
Rn = Bits32(opcode, 19, 16);
3495
Rm = Bits32(opcode, 3, 0);
3496
shift_n = DecodeImmShiftARM(opcode, shift_t);
3497
break;
3498
default:
3499
return false;
3500
}
3501
// Read the register value from register Rn.
3502
uint32_t val1 = ReadCoreReg(Rn, &success);
3503
if (!success)
3504
return false;
3505
3506
// Read the register value from register Rm.
3507
uint32_t val2 = ReadCoreReg(Rm, &success);
3508
if (!success)
3509
return false;
3510
3511
uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
3512
if (!success)
3513
return false;
3514
AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
3515
3516
EmulateInstruction::Context context;
3517
context.type = EmulateInstruction::eContextImmediate;
3518
context.SetNoArgs();
3519
return WriteFlags(context, res.result, res.carry_out, res.overflow);
3520
}
3521
3522
// Arithmetic Shift Right (immediate) shifts a register value right by an
3523
// immediate number of bits, shifting in copies of its sign bit, and writes the
3524
// result to the destination register. It can optionally update the condition
3525
// flags based on the result.
3526
bool EmulateInstructionARM::EmulateASRImm(const uint32_t opcode,
3527
const ARMEncoding encoding) {
3528
#if 0
3529
// ARM pseudo code...
3530
if ConditionPassed() then
3531
EncodingSpecificOperations();
3532
(result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
3533
if d == 15 then // Can only occur for ARM encoding
3534
ALUWritePC(result); // setflags is always FALSE here
3535
else
3536
R[d] = result;
3537
if setflags then
3538
APSR.N = result<31>;
3539
APSR.Z = IsZeroBit(result);
3540
APSR.C = carry;
3541
// APSR.V unchanged
3542
#endif
3543
3544
return EmulateShiftImm(opcode, encoding, SRType_ASR);
3545
}
3546
3547
// Arithmetic Shift Right (register) shifts a register value right by a
3548
// variable number of bits, shifting in copies of its sign bit, and writes the
3549
// result to the destination register. The variable number of bits is read from
3550
// the bottom byte of a register. It can optionally update the condition flags
3551
// based on the result.
3552
bool EmulateInstructionARM::EmulateASRReg(const uint32_t opcode,
3553
const ARMEncoding encoding) {
3554
#if 0
3555
// ARM pseudo code...
3556
if ConditionPassed() then
3557
EncodingSpecificOperations();
3558
shift_n = UInt(R[m]<7:0>);
3559
(result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
3560
R[d] = result;
3561
if setflags then
3562
APSR.N = result<31>;
3563
APSR.Z = IsZeroBit(result);
3564
APSR.C = carry;
3565
// APSR.V unchanged
3566
#endif
3567
3568
return EmulateShiftReg(opcode, encoding, SRType_ASR);
3569
}
3570
3571
// Logical Shift Left (immediate) shifts a register value left by an immediate
3572
// number of bits, shifting in zeros, and writes the result to the destination
3573
// register. It can optionally update the condition flags based on the result.
3574
bool EmulateInstructionARM::EmulateLSLImm(const uint32_t opcode,
3575
const ARMEncoding encoding) {
3576
#if 0
3577
// ARM pseudo code...
3578
if ConditionPassed() then
3579
EncodingSpecificOperations();
3580
(result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
3581
if d == 15 then // Can only occur for ARM encoding
3582
ALUWritePC(result); // setflags is always FALSE here
3583
else
3584
R[d] = result;
3585
if setflags then
3586
APSR.N = result<31>;
3587
APSR.Z = IsZeroBit(result);
3588
APSR.C = carry;
3589
// APSR.V unchanged
3590
#endif
3591
3592
return EmulateShiftImm(opcode, encoding, SRType_LSL);
3593
}
3594
3595
// Logical Shift Left (register) shifts a register value left by a variable
3596
// number of bits, shifting in zeros, and writes the result to the destination
3597
// register. The variable number of bits is read from the bottom byte of a
3598
// register. It can optionally update the condition flags based on the result.
3599
bool EmulateInstructionARM::EmulateLSLReg(const uint32_t opcode,
3600
const ARMEncoding encoding) {
3601
#if 0
3602
// ARM pseudo code...
3603
if ConditionPassed() then
3604
EncodingSpecificOperations();
3605
shift_n = UInt(R[m]<7:0>);
3606
(result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
3607
R[d] = result;
3608
if setflags then
3609
APSR.N = result<31>;
3610
APSR.Z = IsZeroBit(result);
3611
APSR.C = carry;
3612
// APSR.V unchanged
3613
#endif
3614
3615
return EmulateShiftReg(opcode, encoding, SRType_LSL);
3616
}
3617
3618
// Logical Shift Right (immediate) shifts a register value right by an
3619
// immediate number of bits, shifting in zeros, and writes the result to the
3620
// destination register. It can optionally update the condition flags based on
3621
// the result.
3622
bool EmulateInstructionARM::EmulateLSRImm(const uint32_t opcode,
3623
const ARMEncoding encoding) {
3624
#if 0
3625
// ARM pseudo code...
3626
if ConditionPassed() then
3627
EncodingSpecificOperations();
3628
(result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3629
if d == 15 then // Can only occur for ARM encoding
3630
ALUWritePC(result); // setflags is always FALSE here
3631
else
3632
R[d] = result;
3633
if setflags then
3634
APSR.N = result<31>;
3635
APSR.Z = IsZeroBit(result);
3636
APSR.C = carry;
3637
// APSR.V unchanged
3638
#endif
3639
3640
return EmulateShiftImm(opcode, encoding, SRType_LSR);
3641
}
3642
3643
// Logical Shift Right (register) shifts a register value right by a variable
3644
// number of bits, shifting in zeros, and writes the result to the destination
3645
// register. The variable number of bits is read from the bottom byte of a
3646
// register. It can optionally update the condition flags based on the result.
3647
bool EmulateInstructionARM::EmulateLSRReg(const uint32_t opcode,
3648
const ARMEncoding encoding) {
3649
#if 0
3650
// ARM pseudo code...
3651
if ConditionPassed() then
3652
EncodingSpecificOperations();
3653
shift_n = UInt(R[m]<7:0>);
3654
(result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3655
R[d] = result;
3656
if setflags then
3657
APSR.N = result<31>;
3658
APSR.Z = IsZeroBit(result);
3659
APSR.C = carry;
3660
// APSR.V unchanged
3661
#endif
3662
3663
return EmulateShiftReg(opcode, encoding, SRType_LSR);
3664
}
3665
3666
// Rotate Right (immediate) provides the value of the contents of a register
3667
// rotated by a constant value. The bits that are rotated off the right end are
3668
// inserted into the vacated bit positions on the left. It can optionally
3669
// update the condition flags based on the result.
3670
bool EmulateInstructionARM::EmulateRORImm(const uint32_t opcode,
3671
const ARMEncoding encoding) {
3672
#if 0
3673
// ARM pseudo code...
3674
if ConditionPassed() then
3675
EncodingSpecificOperations();
3676
(result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3677
if d == 15 then // Can only occur for ARM encoding
3678
ALUWritePC(result); // setflags is always FALSE here
3679
else
3680
R[d] = result;
3681
if setflags then
3682
APSR.N = result<31>;
3683
APSR.Z = IsZeroBit(result);
3684
APSR.C = carry;
3685
// APSR.V unchanged
3686
#endif
3687
3688
return EmulateShiftImm(opcode, encoding, SRType_ROR);
3689
}
3690
3691
// Rotate Right (register) provides the value of the contents of a register
3692
// rotated by a variable number of bits. The bits that are rotated off the
3693
// right end are inserted into the vacated bit positions on the left. The
3694
// variable number of bits is read from the bottom byte of a register. It can
3695
// optionally update the condition flags based on the result.
3696
bool EmulateInstructionARM::EmulateRORReg(const uint32_t opcode,
3697
const ARMEncoding encoding) {
3698
#if 0
3699
// ARM pseudo code...
3700
if ConditionPassed() then
3701
EncodingSpecificOperations();
3702
shift_n = UInt(R[m]<7:0>);
3703
(result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3704
R[d] = result;
3705
if setflags then
3706
APSR.N = result<31>;
3707
APSR.Z = IsZeroBit(result);
3708
APSR.C = carry;
3709
// APSR.V unchanged
3710
#endif
3711
3712
return EmulateShiftReg(opcode, encoding, SRType_ROR);
3713
}
3714
3715
// Rotate Right with Extend provides the value of the contents of a register
3716
// shifted right by one place, with the carry flag shifted into bit [31].
3717
//
3718
// RRX can optionally update the condition flags based on the result.
3719
// In that case, bit [0] is shifted into the carry flag.
3720
bool EmulateInstructionARM::EmulateRRX(const uint32_t opcode,
3721
const ARMEncoding encoding) {
3722
#if 0
3723
// ARM pseudo code...
3724
if ConditionPassed() then
3725
EncodingSpecificOperations();
3726
(result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3727
if d == 15 then // Can only occur for ARM encoding
3728
ALUWritePC(result); // setflags is always FALSE here
3729
else
3730
R[d] = result;
3731
if setflags then
3732
APSR.N = result<31>;
3733
APSR.Z = IsZeroBit(result);
3734
APSR.C = carry;
3735
// APSR.V unchanged
3736
#endif
3737
3738
return EmulateShiftImm(opcode, encoding, SRType_RRX);
3739
}
3740
3741
bool EmulateInstructionARM::EmulateShiftImm(const uint32_t opcode,
3742
const ARMEncoding encoding,
3743
ARM_ShifterType shift_type) {
3744
// assert(shift_type == SRType_ASR
3745
// || shift_type == SRType_LSL
3746
// || shift_type == SRType_LSR
3747
// || shift_type == SRType_ROR
3748
// || shift_type == SRType_RRX);
3749
3750
bool success = false;
3751
3752
if (ConditionPassed(opcode)) {
3753
uint32_t Rd; // the destination register
3754
uint32_t Rm; // the first operand register
3755
uint32_t imm5; // encoding for the shift amount
3756
uint32_t carry; // the carry bit after the shift operation
3757
bool setflags;
3758
3759
// Special case handling!
3760
// A8.6.139 ROR (immediate) -- Encoding T1
3761
ARMEncoding use_encoding = encoding;
3762
if (shift_type == SRType_ROR && use_encoding == eEncodingT1) {
3763
// Morph the T1 encoding from the ARM Architecture Manual into T2
3764
// encoding to have the same decoding of bit fields as the other Thumb2
3765
// shift operations.
3766
use_encoding = eEncodingT2;
3767
}
3768
3769
switch (use_encoding) {
3770
case eEncodingT1:
3771
Rd = Bits32(opcode, 2, 0);
3772
Rm = Bits32(opcode, 5, 3);
3773
setflags = !InITBlock();
3774
imm5 = Bits32(opcode, 10, 6);
3775
break;
3776
case eEncodingT2:
3777
// A8.6.141 RRX
3778
// There's no imm form of RRX instructions.
3779
if (shift_type == SRType_RRX)
3780
return false;
3781
3782
Rd = Bits32(opcode, 11, 8);
3783
Rm = Bits32(opcode, 3, 0);
3784
setflags = BitIsSet(opcode, 20);
3785
imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3786
if (BadReg(Rd) || BadReg(Rm))
3787
return false;
3788
break;
3789
case eEncodingA1:
3790
Rd = Bits32(opcode, 15, 12);
3791
Rm = Bits32(opcode, 3, 0);
3792
setflags = BitIsSet(opcode, 20);
3793
imm5 = Bits32(opcode, 11, 7);
3794
break;
3795
default:
3796
return false;
3797
}
3798
3799
// A8.6.139 ROR (immediate)
3800
if (shift_type == SRType_ROR && imm5 == 0)
3801
shift_type = SRType_RRX;
3802
3803
// Get the first operand.
3804
uint32_t value = ReadCoreReg(Rm, &success);
3805
if (!success)
3806
return false;
3807
3808
// Decode the shift amount if not RRX.
3809
uint32_t amt =
3810
(shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
3811
3812
uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3813
if (!success)
3814
return false;
3815
3816
// The context specifies that an immediate is to be moved into Rd.
3817
EmulateInstruction::Context context;
3818
context.type = EmulateInstruction::eContextImmediate;
3819
context.SetNoArgs();
3820
3821
if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3822
return false;
3823
}
3824
return true;
3825
}
3826
3827
bool EmulateInstructionARM::EmulateShiftReg(const uint32_t opcode,
3828
const ARMEncoding encoding,
3829
ARM_ShifterType shift_type) {
3830
// assert(shift_type == SRType_ASR
3831
// || shift_type == SRType_LSL
3832
// || shift_type == SRType_LSR
3833
// || shift_type == SRType_ROR);
3834
3835
bool success = false;
3836
3837
if (ConditionPassed(opcode)) {
3838
uint32_t Rd; // the destination register
3839
uint32_t Rn; // the first operand register
3840
uint32_t
3841
Rm; // the register whose bottom byte contains the amount to shift by
3842
uint32_t carry; // the carry bit after the shift operation
3843
bool setflags;
3844
switch (encoding) {
3845
case eEncodingT1:
3846
Rd = Bits32(opcode, 2, 0);
3847
Rn = Rd;
3848
Rm = Bits32(opcode, 5, 3);
3849
setflags = !InITBlock();
3850
break;
3851
case eEncodingT2:
3852
Rd = Bits32(opcode, 11, 8);
3853
Rn = Bits32(opcode, 19, 16);
3854
Rm = Bits32(opcode, 3, 0);
3855
setflags = BitIsSet(opcode, 20);
3856
if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3857
return false;
3858
break;
3859
case eEncodingA1:
3860
Rd = Bits32(opcode, 15, 12);
3861
Rn = Bits32(opcode, 3, 0);
3862
Rm = Bits32(opcode, 11, 8);
3863
setflags = BitIsSet(opcode, 20);
3864
if (Rd == 15 || Rn == 15 || Rm == 15)
3865
return false;
3866
break;
3867
default:
3868
return false;
3869
}
3870
3871
// Get the first operand.
3872
uint32_t value = ReadCoreReg(Rn, &success);
3873
if (!success)
3874
return false;
3875
// Get the Rm register content.
3876
uint32_t val = ReadCoreReg(Rm, &success);
3877
if (!success)
3878
return false;
3879
3880
// Get the shift amount.
3881
uint32_t amt = Bits32(val, 7, 0);
3882
3883
uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3884
if (!success)
3885
return false;
3886
3887
// The context specifies that an immediate is to be moved into Rd.
3888
EmulateInstruction::Context context;
3889
context.type = EmulateInstruction::eContextImmediate;
3890
context.SetNoArgs();
3891
3892
if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3893
return false;
3894
}
3895
return true;
3896
}
3897
3898
// LDM loads multiple registers from consecutive memory locations, using an
3899
// address from a base register. Optionally the address just above the highest
3900
// of those locations can be written back to the base register.
3901
bool EmulateInstructionARM::EmulateLDM(const uint32_t opcode,
3902
const ARMEncoding encoding) {
3903
#if 0
3904
// ARM pseudo code...
3905
if ConditionPassed()
3906
EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3907
address = R[n];
3908
3909
for i = 0 to 14
3910
if registers<i> == '1' then
3911
R[i] = MemA[address, 4]; address = address + 4;
3912
if registers<15> == '1' then
3913
LoadWritePC (MemA[address, 4]);
3914
3915
if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3916
if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3917
3918
#endif
3919
3920
bool success = false;
3921
if (ConditionPassed(opcode)) {
3922
uint32_t n;
3923
uint32_t registers = 0;
3924
bool wback;
3925
const uint32_t addr_byte_size = GetAddressByteSize();
3926
switch (encoding) {
3927
case eEncodingT1:
3928
// n = UInt(Rn); registers = '00000000':register_list; wback =
3929
// (registers<n> == '0');
3930
n = Bits32(opcode, 10, 8);
3931
registers = Bits32(opcode, 7, 0);
3932
registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
3933
wback = BitIsClear(registers, n);
3934
// if BitCount(registers) < 1 then UNPREDICTABLE;
3935
if (BitCount(registers) < 1)
3936
return false;
3937
break;
3938
case eEncodingT2:
3939
// if W == '1' && Rn == '1101' then SEE POP;
3940
// n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
3941
n = Bits32(opcode, 19, 16);
3942
registers = Bits32(opcode, 15, 0);
3943
registers = registers & 0xdfff; // Make sure bit 13 is zero.
3944
wback = BitIsSet(opcode, 21);
3945
3946
// if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then
3947
// UNPREDICTABLE;
3948
if ((n == 15) || (BitCount(registers) < 2) ||
3949
(BitIsSet(opcode, 14) && BitIsSet(opcode, 15)))
3950
return false;
3951
3952
// if registers<15> == '1' && InITBlock() && !LastInITBlock() then
3953
// UNPREDICTABLE;
3954
if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
3955
return false;
3956
3957
// if wback && registers<n> == '1' then UNPREDICTABLE;
3958
if (wback && BitIsSet(registers, n))
3959
return false;
3960
break;
3961
3962
case eEncodingA1:
3963
n = Bits32(opcode, 19, 16);
3964
registers = Bits32(opcode, 15, 0);
3965
wback = BitIsSet(opcode, 21);
3966
if ((n == 15) || (BitCount(registers) < 1))
3967
return false;
3968
break;
3969
default:
3970
return false;
3971
}
3972
3973
int32_t offset = 0;
3974
const addr_t base_address =
3975
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3976
if (!success)
3977
return false;
3978
3979
EmulateInstruction::Context context;
3980
context.type = EmulateInstruction::eContextRegisterPlusOffset;
3981
std::optional<RegisterInfo> dwarf_reg =
3982
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
3983
context.SetRegisterPlusOffset(*dwarf_reg, offset);
3984
3985
for (int i = 0; i < 14; ++i) {
3986
if (BitIsSet(registers, i)) {
3987
context.type = EmulateInstruction::eContextRegisterPlusOffset;
3988
context.SetRegisterPlusOffset(*dwarf_reg, offset);
3989
if (wback && (n == 13)) // Pop Instruction
3990
{
3991
context.type = EmulateInstruction::eContextPopRegisterOffStack;
3992
context.SetAddress(base_address + offset);
3993
}
3994
3995
// R[i] = MemA [address, 4]; address = address + 4;
3996
uint32_t data = MemARead(context, base_address + offset, addr_byte_size,
3997
0, &success);
3998
if (!success)
3999
return false;
4000
4001
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4002
data))
4003
return false;
4004
4005
offset += addr_byte_size;
4006
}
4007
}
4008
4009
if (BitIsSet(registers, 15)) {
4010
// LoadWritePC (MemA [address, 4]);
4011
context.type = EmulateInstruction::eContextRegisterPlusOffset;
4012
context.SetRegisterPlusOffset(*dwarf_reg, offset);
4013
uint32_t data =
4014
MemARead(context, base_address + offset, addr_byte_size, 0, &success);
4015
if (!success)
4016
return false;
4017
// In ARMv5T and above, this is an interworking branch.
4018
if (!LoadWritePC(context, data))
4019
return false;
4020
}
4021
4022
if (wback && BitIsClear(registers, n)) {
4023
// R[n] = R[n] + 4 * BitCount (registers)
4024
int32_t offset = addr_byte_size * BitCount(registers);
4025
context.type = EmulateInstruction::eContextAdjustBaseRegister;
4026
context.SetRegisterPlusOffset(*dwarf_reg, offset);
4027
4028
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4029
base_address + offset))
4030
return false;
4031
}
4032
if (wback && BitIsSet(registers, n))
4033
// R[n] bits(32) UNKNOWN;
4034
return WriteBits32Unknown(n);
4035
}
4036
return true;
4037
}
4038
4039
// LDMDA loads multiple registers from consecutive memory locations using an
4040
// address from a base register.
4041
// The consecutive memory locations end at this address and the address just
4042
// below the lowest of those locations can optionally be written back to the
4043
// base register.
4044
bool EmulateInstructionARM::EmulateLDMDA(const uint32_t opcode,
4045
const ARMEncoding encoding) {
4046
#if 0
4047
// ARM pseudo code...
4048
if ConditionPassed() then
4049
EncodingSpecificOperations();
4050
address = R[n] - 4*BitCount(registers) + 4;
4051
4052
for i = 0 to 14
4053
if registers<i> == '1' then
4054
R[i] = MemA[address,4]; address = address + 4;
4055
4056
if registers<15> == '1' then
4057
LoadWritePC(MemA[address,4]);
4058
4059
if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4060
if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4061
#endif
4062
4063
bool success = false;
4064
4065
if (ConditionPassed(opcode)) {
4066
uint32_t n;
4067
uint32_t registers = 0;
4068
bool wback;
4069
const uint32_t addr_byte_size = GetAddressByteSize();
4070
4071
// EncodingSpecificOperations();
4072
switch (encoding) {
4073
case eEncodingA1:
4074
// n = UInt(Rn); registers = register_list; wback = (W == '1');
4075
n = Bits32(opcode, 19, 16);
4076
registers = Bits32(opcode, 15, 0);
4077
wback = BitIsSet(opcode, 21);
4078
4079
// if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4080
if ((n == 15) || (BitCount(registers) < 1))
4081
return false;
4082
4083
break;
4084
4085
default:
4086
return false;
4087
}
4088
// address = R[n] - 4*BitCount(registers) + 4;
4089
4090
int32_t offset = 0;
4091
addr_t Rn = ReadCoreReg(n, &success);
4092
4093
if (!success)
4094
return false;
4095
4096
addr_t address =
4097
Rn - (addr_byte_size * BitCount(registers)) + addr_byte_size;
4098
4099
EmulateInstruction::Context context;
4100
context.type = EmulateInstruction::eContextRegisterPlusOffset;
4101
std::optional<RegisterInfo> dwarf_reg =
4102
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
4103
context.SetRegisterPlusOffset(*dwarf_reg, offset);
4104
4105
// for i = 0 to 14
4106
for (int i = 0; i < 14; ++i) {
4107
// if registers<i> == '1' then
4108
if (BitIsSet(registers, i)) {
4109
// R[i] = MemA[address,4]; address = address + 4;
4110
context.SetRegisterPlusOffset(*dwarf_reg, Rn - (address + offset));
4111
uint32_t data =
4112
MemARead(context, address + offset, addr_byte_size, 0, &success);
4113
if (!success)
4114
return false;
4115
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4116
data))
4117
return false;
4118
offset += addr_byte_size;
4119
}
4120
}
4121
4122
// if registers<15> == '1' then
4123
// LoadWritePC(MemA[address,4]);
4124
if (BitIsSet(registers, 15)) {
4125
context.SetRegisterPlusOffset(*dwarf_reg, offset);
4126
uint32_t data =
4127
MemARead(context, address + offset, addr_byte_size, 0, &success);
4128
if (!success)
4129
return false;
4130
// In ARMv5T and above, this is an interworking branch.
4131
if (!LoadWritePC(context, data))
4132
return false;
4133
}
4134
4135
// if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4136
if (wback && BitIsClear(registers, n)) {
4137
4138
offset = (addr_byte_size * BitCount(registers)) * -1;
4139
context.type = EmulateInstruction::eContextAdjustBaseRegister;
4140
context.SetImmediateSigned(offset);
4141
addr_t addr = Rn + offset;
4142
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4143
addr))
4144
return false;
4145
}
4146
4147
// if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4148
if (wback && BitIsSet(registers, n))
4149
return WriteBits32Unknown(n);
4150
}
4151
return true;
4152
}
4153
4154
// LDMDB loads multiple registers from consecutive memory locations using an
4155
// address from a base register. The
4156
// consecutive memory locations end just below this address, and the address of
4157
// the lowest of those locations can be optionally written back to the base
4158
// register.
4159
bool EmulateInstructionARM::EmulateLDMDB(const uint32_t opcode,
4160
const ARMEncoding encoding) {
4161
#if 0
4162
// ARM pseudo code...
4163
if ConditionPassed() then
4164
EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4165
address = R[n] - 4*BitCount(registers);
4166
4167
for i = 0 to 14
4168
if registers<i> == '1' then
4169
R[i] = MemA[address,4]; address = address + 4;
4170
if registers<15> == '1' then
4171
LoadWritePC(MemA[address,4]);
4172
4173
if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4174
if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
4175
#endif
4176
4177
bool success = false;
4178
4179
if (ConditionPassed(opcode)) {
4180
uint32_t n;
4181
uint32_t registers = 0;
4182
bool wback;
4183
const uint32_t addr_byte_size = GetAddressByteSize();
4184
switch (encoding) {
4185
case eEncodingT1:
4186
// n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
4187
n = Bits32(opcode, 19, 16);
4188
registers = Bits32(opcode, 15, 0);
4189
registers = registers & 0xdfff; // Make sure bit 13 is a zero.
4190
wback = BitIsSet(opcode, 21);
4191
4192
// if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then
4193
// UNPREDICTABLE;
4194
if ((n == 15) || (BitCount(registers) < 2) ||
4195
(BitIsSet(opcode, 14) && BitIsSet(opcode, 15)))
4196
return false;
4197
4198
// if registers<15> == '1' && InITBlock() && !LastInITBlock() then
4199
// UNPREDICTABLE;
4200
if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
4201
return false;
4202
4203
// if wback && registers<n> == '1' then UNPREDICTABLE;
4204
if (wback && BitIsSet(registers, n))
4205
return false;
4206
4207
break;
4208
4209
case eEncodingA1:
4210
// n = UInt(Rn); registers = register_list; wback = (W == '1');
4211
n = Bits32(opcode, 19, 16);
4212
registers = Bits32(opcode, 15, 0);
4213
wback = BitIsSet(opcode, 21);
4214
4215
// if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4216
if ((n == 15) || (BitCount(registers) < 1))
4217
return false;
4218
4219
break;
4220
4221
default:
4222
return false;
4223
}
4224
4225
// address = R[n] - 4*BitCount(registers);
4226
4227
int32_t offset = 0;
4228
addr_t Rn =
4229
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4230
4231
if (!success)
4232
return false;
4233
4234
addr_t address = Rn - (addr_byte_size * BitCount(registers));
4235
EmulateInstruction::Context context;
4236
context.type = EmulateInstruction::eContextRegisterPlusOffset;
4237
std::optional<RegisterInfo> dwarf_reg =
4238
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
4239
context.SetRegisterPlusOffset(*dwarf_reg, Rn - address);
4240
4241
for (int i = 0; i < 14; ++i) {
4242
if (BitIsSet(registers, i)) {
4243
// R[i] = MemA[address,4]; address = address + 4;
4244
context.SetRegisterPlusOffset(*dwarf_reg, Rn - (address + offset));
4245
uint32_t data =
4246
MemARead(context, address + offset, addr_byte_size, 0, &success);
4247
if (!success)
4248
return false;
4249
4250
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4251
data))
4252
return false;
4253
4254
offset += addr_byte_size;
4255
}
4256
}
4257
4258
// if registers<15> == '1' then
4259
// LoadWritePC(MemA[address,4]);
4260
if (BitIsSet(registers, 15)) {
4261
context.SetRegisterPlusOffset(*dwarf_reg, offset);
4262
uint32_t data =
4263
MemARead(context, address + offset, addr_byte_size, 0, &success);
4264
if (!success)
4265
return false;
4266
// In ARMv5T and above, this is an interworking branch.
4267
if (!LoadWritePC(context, data))
4268
return false;
4269
}
4270
4271
// if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4272
if (wback && BitIsClear(registers, n)) {
4273
4274
offset = (addr_byte_size * BitCount(registers)) * -1;
4275
context.type = EmulateInstruction::eContextAdjustBaseRegister;
4276
context.SetImmediateSigned(offset);
4277
addr_t addr = Rn + offset;
4278
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4279
addr))
4280
return false;
4281
}
4282
4283
// if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only
4284
// possible for encoding A1
4285
if (wback && BitIsSet(registers, n))
4286
return WriteBits32Unknown(n);
4287
}
4288
return true;
4289
}
4290
4291
// LDMIB loads multiple registers from consecutive memory locations using an
4292
// address from a base register. The
4293
// consecutive memory locations start just above this address, and thea ddress
4294
// of the last of those locations can optinoally be written back to the base
4295
// register.
4296
bool EmulateInstructionARM::EmulateLDMIB(const uint32_t opcode,
4297
const ARMEncoding encoding) {
4298
#if 0
4299
if ConditionPassed() then
4300
EncodingSpecificOperations();
4301
address = R[n] + 4;
4302
4303
for i = 0 to 14
4304
if registers<i> == '1' then
4305
R[i] = MemA[address,4]; address = address + 4;
4306
if registers<15> == '1' then
4307
LoadWritePC(MemA[address,4]);
4308
4309
if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
4310
if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4311
#endif
4312
4313
bool success = false;
4314
4315
if (ConditionPassed(opcode)) {
4316
uint32_t n;
4317
uint32_t registers = 0;
4318
bool wback;
4319
const uint32_t addr_byte_size = GetAddressByteSize();
4320
switch (encoding) {
4321
case eEncodingA1:
4322
// n = UInt(Rn); registers = register_list; wback = (W == '1');
4323
n = Bits32(opcode, 19, 16);
4324
registers = Bits32(opcode, 15, 0);
4325
wback = BitIsSet(opcode, 21);
4326
4327
// if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4328
if ((n == 15) || (BitCount(registers) < 1))
4329
return false;
4330
4331
break;
4332
default:
4333
return false;
4334
}
4335
// address = R[n] + 4;
4336
4337
int32_t offset = 0;
4338
addr_t Rn =
4339
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4340
4341
if (!success)
4342
return false;
4343
4344
addr_t address = Rn + addr_byte_size;
4345
4346
EmulateInstruction::Context context;
4347
context.type = EmulateInstruction::eContextRegisterPlusOffset;
4348
std::optional<RegisterInfo> dwarf_reg =
4349
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
4350
context.SetRegisterPlusOffset(*dwarf_reg, offset);
4351
4352
for (int i = 0; i < 14; ++i) {
4353
if (BitIsSet(registers, i)) {
4354
// R[i] = MemA[address,4]; address = address + 4;
4355
4356
context.SetRegisterPlusOffset(*dwarf_reg, offset + addr_byte_size);
4357
uint32_t data =
4358
MemARead(context, address + offset, addr_byte_size, 0, &success);
4359
if (!success)
4360
return false;
4361
4362
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4363
data))
4364
return false;
4365
4366
offset += addr_byte_size;
4367
}
4368
}
4369
4370
// if registers<15> == '1' then
4371
// LoadWritePC(MemA[address,4]);
4372
if (BitIsSet(registers, 15)) {
4373
context.SetRegisterPlusOffset(*dwarf_reg, offset);
4374
uint32_t data =
4375
MemARead(context, address + offset, addr_byte_size, 0, &success);
4376
if (!success)
4377
return false;
4378
// In ARMv5T and above, this is an interworking branch.
4379
if (!LoadWritePC(context, data))
4380
return false;
4381
}
4382
4383
// if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
4384
if (wback && BitIsClear(registers, n)) {
4385
4386
offset = addr_byte_size * BitCount(registers);
4387
context.type = EmulateInstruction::eContextAdjustBaseRegister;
4388
context.SetImmediateSigned(offset);
4389
addr_t addr = Rn + offset;
4390
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4391
addr))
4392
return false;
4393
}
4394
4395
// if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only
4396
// possible for encoding A1
4397
if (wback && BitIsSet(registers, n))
4398
return WriteBits32Unknown(n);
4399
}
4400
return true;
4401
}
4402
4403
// Load Register (immediate) calculates an address from a base register value
4404
// and an immediate offset, loads a word from memory, and writes to a register.
4405
// LDR (immediate, Thumb)
4406
bool EmulateInstructionARM::EmulateLDRRtRnImm(const uint32_t opcode,
4407
const ARMEncoding encoding) {
4408
#if 0
4409
// ARM pseudo code...
4410
if (ConditionPassed())
4411
{
4412
EncodingSpecificOperations(); NullCheckIfThumbEE(15);
4413
offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4414
address = if index then offset_addr else R[n];
4415
data = MemU[address,4];
4416
if wback then R[n] = offset_addr;
4417
if t == 15 then
4418
if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
4419
elsif UnalignedSupport() || address<1:0> = '00' then
4420
R[t] = data;
4421
else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
4422
}
4423
#endif
4424
4425
bool success = false;
4426
4427
if (ConditionPassed(opcode)) {
4428
uint32_t Rt; // the destination register
4429
uint32_t Rn; // the base register
4430
uint32_t imm32; // the immediate offset used to form the address
4431
addr_t offset_addr; // the offset address
4432
addr_t address; // the calculated address
4433
uint32_t data; // the literal data value from memory load
4434
bool add, index, wback;
4435
switch (encoding) {
4436
case eEncodingT1:
4437
Rt = Bits32(opcode, 2, 0);
4438
Rn = Bits32(opcode, 5, 3);
4439
imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
4440
// index = TRUE; add = TRUE; wback = FALSE
4441
add = true;
4442
index = true;
4443
wback = false;
4444
4445
break;
4446
4447
case eEncodingT2:
4448
// t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
4449
Rt = Bits32(opcode, 10, 8);
4450
Rn = 13;
4451
imm32 = Bits32(opcode, 7, 0) << 2;
4452
4453
// index = TRUE; add = TRUE; wback = FALSE;
4454
index = true;
4455
add = true;
4456
wback = false;
4457
4458
break;
4459
4460
case eEncodingT3:
4461
// if Rn == '1111' then SEE LDR (literal);
4462
// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4463
Rt = Bits32(opcode, 15, 12);
4464
Rn = Bits32(opcode, 19, 16);
4465
imm32 = Bits32(opcode, 11, 0);
4466
4467
// index = TRUE; add = TRUE; wback = FALSE;
4468
index = true;
4469
add = true;
4470
wback = false;
4471
4472
// if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
4473
if ((Rt == 15) && InITBlock() && !LastInITBlock())
4474
return false;
4475
4476
break;
4477
4478
case eEncodingT4:
4479
// if Rn == '1111' then SEE LDR (literal);
4480
// if P == '1' && U == '1' && W == '0' then SEE LDRT;
4481
// if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 ==
4482
// '00000100' then SEE POP;
4483
// if P == '0' && W == '0' then UNDEFINED;
4484
if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
4485
return false;
4486
4487
// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4488
Rt = Bits32(opcode, 15, 12);
4489
Rn = Bits32(opcode, 19, 16);
4490
imm32 = Bits32(opcode, 7, 0);
4491
4492
// index = (P == '1'); add = (U == '1'); wback = (W == '1');
4493
index = BitIsSet(opcode, 10);
4494
add = BitIsSet(opcode, 9);
4495
wback = BitIsSet(opcode, 8);
4496
4497
// if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock())
4498
// then UNPREDICTABLE;
4499
if ((wback && (Rn == Rt)) ||
4500
((Rt == 15) && InITBlock() && !LastInITBlock()))
4501
return false;
4502
4503
break;
4504
4505
default:
4506
return false;
4507
}
4508
uint32_t base = ReadCoreReg(Rn, &success);
4509
if (!success)
4510
return false;
4511
if (add)
4512
offset_addr = base + imm32;
4513
else
4514
offset_addr = base - imm32;
4515
4516
address = (index ? offset_addr : base);
4517
4518
std::optional<RegisterInfo> base_reg =
4519
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn);
4520
if (wback) {
4521
EmulateInstruction::Context ctx;
4522
if (Rn == 13) {
4523
ctx.type = eContextAdjustStackPointer;
4524
ctx.SetImmediateSigned((int32_t)(offset_addr - base));
4525
} else if (Rn == GetFramePointerRegisterNumber()) {
4526
ctx.type = eContextSetFramePointer;
4527
ctx.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base));
4528
} else {
4529
ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
4530
ctx.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base));
4531
}
4532
4533
if (!WriteRegisterUnsigned(ctx, eRegisterKindDWARF, dwarf_r0 + Rn,
4534
offset_addr))
4535
return false;
4536
}
4537
4538
// Prepare to write to the Rt register.
4539
EmulateInstruction::Context context;
4540
context.type = EmulateInstruction::eContextRegisterLoad;
4541
context.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base));
4542
4543
// Read memory from the address.
4544
data = MemURead(context, address, 4, 0, &success);
4545
if (!success)
4546
return false;
4547
4548
if (Rt == 15) {
4549
if (Bits32(address, 1, 0) == 0) {
4550
if (!LoadWritePC(context, data))
4551
return false;
4552
} else
4553
return false;
4554
} else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) {
4555
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rt,
4556
data))
4557
return false;
4558
} else
4559
WriteBits32Unknown(Rt);
4560
}
4561
return true;
4562
}
4563
4564
// STM (Store Multiple Increment After) stores multiple registers to consecutive
4565
// memory locations using an address
4566
// from a base register. The consecutive memory locations start at this
4567
// address, and the address just above the last of those locations can
4568
// optionally be written back to the base register.
4569
bool EmulateInstructionARM::EmulateSTM(const uint32_t opcode,
4570
const ARMEncoding encoding) {
4571
#if 0
4572
if ConditionPassed() then
4573
EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4574
address = R[n];
4575
4576
for i = 0 to 14
4577
if registers<i> == '1' then
4578
if i == n && wback && i != LowestSetBit(registers) then
4579
MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
4580
else
4581
MemA[address,4] = R[i];
4582
address = address + 4;
4583
4584
if registers<15> == '1' then // Only possible for encoding A1
4585
MemA[address,4] = PCStoreValue();
4586
if wback then R[n] = R[n] + 4*BitCount(registers);
4587
#endif
4588
4589
bool success = false;
4590
4591
if (ConditionPassed(opcode)) {
4592
uint32_t n;
4593
uint32_t registers = 0;
4594
bool wback;
4595
const uint32_t addr_byte_size = GetAddressByteSize();
4596
4597
// EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4598
switch (encoding) {
4599
case eEncodingT1:
4600
// n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
4601
n = Bits32(opcode, 10, 8);
4602
registers = Bits32(opcode, 7, 0);
4603
registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
4604
wback = true;
4605
4606
// if BitCount(registers) < 1 then UNPREDICTABLE;
4607
if (BitCount(registers) < 1)
4608
return false;
4609
4610
break;
4611
4612
case eEncodingT2:
4613
// n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4614
n = Bits32(opcode, 19, 16);
4615
registers = Bits32(opcode, 15, 0);
4616
registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4617
wback = BitIsSet(opcode, 21);
4618
4619
// if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4620
if ((n == 15) || (BitCount(registers) < 2))
4621
return false;
4622
4623
// if wback && registers<n> == '1' then UNPREDICTABLE;
4624
if (wback && BitIsSet(registers, n))
4625
return false;
4626
4627
break;
4628
4629
case eEncodingA1:
4630
// n = UInt(Rn); registers = register_list; wback = (W == '1');
4631
n = Bits32(opcode, 19, 16);
4632
registers = Bits32(opcode, 15, 0);
4633
wback = BitIsSet(opcode, 21);
4634
4635
// if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4636
if ((n == 15) || (BitCount(registers) < 1))
4637
return false;
4638
4639
break;
4640
4641
default:
4642
return false;
4643
}
4644
4645
// address = R[n];
4646
int32_t offset = 0;
4647
const addr_t address =
4648
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4649
if (!success)
4650
return false;
4651
4652
EmulateInstruction::Context context;
4653
context.type = EmulateInstruction::eContextRegisterStore;
4654
std::optional<RegisterInfo> base_reg =
4655
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
4656
4657
// for i = 0 to 14
4658
uint32_t lowest_set_bit = 14;
4659
for (uint32_t i = 0; i < 14; ++i) {
4660
// if registers<i> == '1' then
4661
if (BitIsSet(registers, i)) {
4662
if (i < lowest_set_bit)
4663
lowest_set_bit = i;
4664
// if i == n && wback && i != LowestSetBit(registers) then
4665
if ((i == n) && wback && (i != lowest_set_bit))
4666
// MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings
4667
// T1 and A1
4668
WriteBits32UnknownToMemory(address + offset);
4669
else {
4670
// MemA[address,4] = R[i];
4671
uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
4672
0, &success);
4673
if (!success)
4674
return false;
4675
4676
std::optional<RegisterInfo> data_reg =
4677
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i);
4678
context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, offset);
4679
if (!MemAWrite(context, address + offset, data, addr_byte_size))
4680
return false;
4681
}
4682
4683
// address = address + 4;
4684
offset += addr_byte_size;
4685
}
4686
}
4687
4688
// if registers<15> == '1' then // Only possible for encoding A1
4689
// MemA[address,4] = PCStoreValue();
4690
if (BitIsSet(registers, 15)) {
4691
std::optional<RegisterInfo> pc_reg =
4692
GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);
4693
context.SetRegisterPlusOffset(*pc_reg, 8);
4694
const uint32_t pc = ReadCoreReg(PC_REG, &success);
4695
if (!success)
4696
return false;
4697
4698
if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4699
return false;
4700
}
4701
4702
// if wback then R[n] = R[n] + 4*BitCount(registers);
4703
if (wback) {
4704
offset = addr_byte_size * BitCount(registers);
4705
context.type = EmulateInstruction::eContextAdjustBaseRegister;
4706
context.SetImmediateSigned(offset);
4707
addr_t data = address + offset;
4708
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4709
data))
4710
return false;
4711
}
4712
}
4713
return true;
4714
}
4715
4716
// STMDA (Store Multiple Decrement After) stores multiple registers to
4717
// consecutive memory locations using an address from a base register. The
4718
// consecutive memory locations end at this address, and the address just below
4719
// the lowest of those locations can optionally be written back to the base
4720
// register.
4721
bool EmulateInstructionARM::EmulateSTMDA(const uint32_t opcode,
4722
const ARMEncoding encoding) {
4723
#if 0
4724
if ConditionPassed() then
4725
EncodingSpecificOperations();
4726
address = R[n] - 4*BitCount(registers) + 4;
4727
4728
for i = 0 to 14
4729
if registers<i> == '1' then
4730
if i == n && wback && i != LowestSetBit(registers) then
4731
MemA[address,4] = bits(32) UNKNOWN;
4732
else
4733
MemA[address,4] = R[i];
4734
address = address + 4;
4735
4736
if registers<15> == '1' then
4737
MemA[address,4] = PCStoreValue();
4738
4739
if wback then R[n] = R[n] - 4*BitCount(registers);
4740
#endif
4741
4742
bool success = false;
4743
4744
if (ConditionPassed(opcode)) {
4745
uint32_t n;
4746
uint32_t registers = 0;
4747
bool wback;
4748
const uint32_t addr_byte_size = GetAddressByteSize();
4749
4750
// EncodingSpecificOperations();
4751
switch (encoding) {
4752
case eEncodingA1:
4753
// n = UInt(Rn); registers = register_list; wback = (W == '1');
4754
n = Bits32(opcode, 19, 16);
4755
registers = Bits32(opcode, 15, 0);
4756
wback = BitIsSet(opcode, 21);
4757
4758
// if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4759
if ((n == 15) || (BitCount(registers) < 1))
4760
return false;
4761
break;
4762
default:
4763
return false;
4764
}
4765
4766
// address = R[n] - 4*BitCount(registers) + 4;
4767
int32_t offset = 0;
4768
addr_t Rn = ReadCoreReg(n, &success);
4769
if (!success)
4770
return false;
4771
4772
addr_t address = Rn - (addr_byte_size * BitCount(registers)) + 4;
4773
4774
EmulateInstruction::Context context;
4775
context.type = EmulateInstruction::eContextRegisterStore;
4776
std::optional<RegisterInfo> base_reg =
4777
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
4778
4779
// for i = 0 to 14
4780
uint32_t lowest_bit_set = 14;
4781
for (uint32_t i = 0; i < 14; ++i) {
4782
// if registers<i> == '1' then
4783
if (BitIsSet(registers, i)) {
4784
if (i < lowest_bit_set)
4785
lowest_bit_set = i;
4786
// if i == n && wback && i != LowestSetBit(registers) then
4787
if ((i == n) && wback && (i != lowest_bit_set))
4788
// MemA[address,4] = bits(32) UNKNOWN;
4789
WriteBits32UnknownToMemory(address + offset);
4790
else {
4791
// MemA[address,4] = R[i];
4792
uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
4793
0, &success);
4794
if (!success)
4795
return false;
4796
4797
std::optional<RegisterInfo> data_reg =
4798
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i);
4799
context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
4800
Rn - (address + offset));
4801
if (!MemAWrite(context, address + offset, data, addr_byte_size))
4802
return false;
4803
}
4804
4805
// address = address + 4;
4806
offset += addr_byte_size;
4807
}
4808
}
4809
4810
// if registers<15> == '1' then
4811
// MemA[address,4] = PCStoreValue();
4812
if (BitIsSet(registers, 15)) {
4813
std::optional<RegisterInfo> pc_reg =
4814
GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);
4815
context.SetRegisterPlusOffset(*pc_reg, 8);
4816
const uint32_t pc = ReadCoreReg(PC_REG, &success);
4817
if (!success)
4818
return false;
4819
4820
if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4821
return false;
4822
}
4823
4824
// if wback then R[n] = R[n] - 4*BitCount(registers);
4825
if (wback) {
4826
offset = (addr_byte_size * BitCount(registers)) * -1;
4827
context.type = EmulateInstruction::eContextAdjustBaseRegister;
4828
context.SetImmediateSigned(offset);
4829
addr_t data = Rn + offset;
4830
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4831
data))
4832
return false;
4833
}
4834
}
4835
return true;
4836
}
4837
4838
// STMDB (Store Multiple Decrement Before) stores multiple registers to
4839
// consecutive memory locations using an address from a base register. The
4840
// consecutive memory locations end just below this address, and the address of
4841
// the first of those locations can optionally be written back to the base
4842
// register.
4843
bool EmulateInstructionARM::EmulateSTMDB(const uint32_t opcode,
4844
const ARMEncoding encoding) {
4845
#if 0
4846
if ConditionPassed() then
4847
EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4848
address = R[n] - 4*BitCount(registers);
4849
4850
for i = 0 to 14
4851
if registers<i> == '1' then
4852
if i == n && wback && i != LowestSetBit(registers) then
4853
MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4854
else
4855
MemA[address,4] = R[i];
4856
address = address + 4;
4857
4858
if registers<15> == '1' then // Only possible for encoding A1
4859
MemA[address,4] = PCStoreValue();
4860
4861
if wback then R[n] = R[n] - 4*BitCount(registers);
4862
#endif
4863
4864
bool success = false;
4865
4866
if (ConditionPassed(opcode)) {
4867
uint32_t n;
4868
uint32_t registers = 0;
4869
bool wback;
4870
const uint32_t addr_byte_size = GetAddressByteSize();
4871
4872
// EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4873
switch (encoding) {
4874
case eEncodingT1:
4875
// if W == '1' && Rn == '1101' then SEE PUSH;
4876
if ((BitIsSet(opcode, 21)) && (Bits32(opcode, 19, 16) == 13)) {
4877
// See PUSH
4878
}
4879
// n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4880
n = Bits32(opcode, 19, 16);
4881
registers = Bits32(opcode, 15, 0);
4882
registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4883
wback = BitIsSet(opcode, 21);
4884
// if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4885
if ((n == 15) || BitCount(registers) < 2)
4886
return false;
4887
// if wback && registers<n> == '1' then UNPREDICTABLE;
4888
if (wback && BitIsSet(registers, n))
4889
return false;
4890
break;
4891
4892
case eEncodingA1:
4893
// if W == '1' && Rn == '1101' && BitCount(register_list) >= 2 then SEE
4894
// PUSH;
4895
if (BitIsSet(opcode, 21) && (Bits32(opcode, 19, 16) == 13) &&
4896
BitCount(Bits32(opcode, 15, 0)) >= 2) {
4897
// See Push
4898
}
4899
// n = UInt(Rn); registers = register_list; wback = (W == '1');
4900
n = Bits32(opcode, 19, 16);
4901
registers = Bits32(opcode, 15, 0);
4902
wback = BitIsSet(opcode, 21);
4903
// if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4904
if ((n == 15) || BitCount(registers) < 1)
4905
return false;
4906
break;
4907
4908
default:
4909
return false;
4910
}
4911
4912
// address = R[n] - 4*BitCount(registers);
4913
4914
int32_t offset = 0;
4915
addr_t Rn =
4916
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4917
if (!success)
4918
return false;
4919
4920
addr_t address = Rn - (addr_byte_size * BitCount(registers));
4921
4922
EmulateInstruction::Context context;
4923
context.type = EmulateInstruction::eContextRegisterStore;
4924
std::optional<RegisterInfo> base_reg =
4925
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
4926
4927
// for i = 0 to 14
4928
uint32_t lowest_set_bit = 14;
4929
for (uint32_t i = 0; i < 14; ++i) {
4930
// if registers<i> == '1' then
4931
if (BitIsSet(registers, i)) {
4932
if (i < lowest_set_bit)
4933
lowest_set_bit = i;
4934
// if i == n && wback && i != LowestSetBit(registers) then
4935
if ((i == n) && wback && (i != lowest_set_bit))
4936
// MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding
4937
// A1
4938
WriteBits32UnknownToMemory(address + offset);
4939
else {
4940
// MemA[address,4] = R[i];
4941
uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
4942
0, &success);
4943
if (!success)
4944
return false;
4945
4946
std::optional<RegisterInfo> data_reg =
4947
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i);
4948
context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
4949
Rn - (address + offset));
4950
if (!MemAWrite(context, address + offset, data, addr_byte_size))
4951
return false;
4952
}
4953
4954
// address = address + 4;
4955
offset += addr_byte_size;
4956
}
4957
}
4958
4959
// if registers<15> == '1' then // Only possible for encoding A1
4960
// MemA[address,4] = PCStoreValue();
4961
if (BitIsSet(registers, 15)) {
4962
std::optional<RegisterInfo> pc_reg =
4963
GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);
4964
context.SetRegisterPlusOffset(*pc_reg, 8);
4965
const uint32_t pc = ReadCoreReg(PC_REG, &success);
4966
if (!success)
4967
return false;
4968
4969
if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4970
return false;
4971
}
4972
4973
// if wback then R[n] = R[n] - 4*BitCount(registers);
4974
if (wback) {
4975
offset = (addr_byte_size * BitCount(registers)) * -1;
4976
context.type = EmulateInstruction::eContextAdjustBaseRegister;
4977
context.SetImmediateSigned(offset);
4978
addr_t data = Rn + offset;
4979
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4980
data))
4981
return false;
4982
}
4983
}
4984
return true;
4985
}
4986
4987
// STMIB (Store Multiple Increment Before) stores multiple registers to
4988
// consecutive memory locations using an address from a base register. The
4989
// consecutive memory locations start just above this address, and the address
4990
// of the last of those locations can optionally be written back to the base
4991
// register.
4992
bool EmulateInstructionARM::EmulateSTMIB(const uint32_t opcode,
4993
const ARMEncoding encoding) {
4994
#if 0
4995
if ConditionPassed() then
4996
EncodingSpecificOperations();
4997
address = R[n] + 4;
4998
4999
for i = 0 to 14
5000
if registers<i> == '1' then
5001
if i == n && wback && i != LowestSetBit(registers) then
5002
MemA[address,4] = bits(32) UNKNOWN;
5003
else
5004
MemA[address,4] = R[i];
5005
address = address + 4;
5006
5007
if registers<15> == '1' then
5008
MemA[address,4] = PCStoreValue();
5009
5010
if wback then R[n] = R[n] + 4*BitCount(registers);
5011
#endif
5012
5013
bool success = false;
5014
5015
if (ConditionPassed(opcode)) {
5016
uint32_t n;
5017
uint32_t registers = 0;
5018
bool wback;
5019
const uint32_t addr_byte_size = GetAddressByteSize();
5020
5021
// EncodingSpecificOperations();
5022
switch (encoding) {
5023
case eEncodingA1:
5024
// n = UInt(Rn); registers = register_list; wback = (W == '1');
5025
n = Bits32(opcode, 19, 16);
5026
registers = Bits32(opcode, 15, 0);
5027
wback = BitIsSet(opcode, 21);
5028
5029
// if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
5030
if ((n == 15) && (BitCount(registers) < 1))
5031
return false;
5032
break;
5033
default:
5034
return false;
5035
}
5036
// address = R[n] + 4;
5037
5038
int32_t offset = 0;
5039
addr_t Rn = ReadCoreReg(n, &success);
5040
if (!success)
5041
return false;
5042
5043
addr_t address = Rn + addr_byte_size;
5044
5045
EmulateInstruction::Context context;
5046
context.type = EmulateInstruction::eContextRegisterStore;
5047
std::optional<RegisterInfo> base_reg =
5048
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
5049
5050
uint32_t lowest_set_bit = 14;
5051
// for i = 0 to 14
5052
for (uint32_t i = 0; i < 14; ++i) {
5053
// if registers<i> == '1' then
5054
if (BitIsSet(registers, i)) {
5055
if (i < lowest_set_bit)
5056
lowest_set_bit = i;
5057
// if i == n && wback && i != LowestSetBit(registers) then
5058
if ((i == n) && wback && (i != lowest_set_bit))
5059
// MemA[address,4] = bits(32) UNKNOWN;
5060
WriteBits32UnknownToMemory(address + offset);
5061
// else
5062
else {
5063
// MemA[address,4] = R[i];
5064
uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
5065
0, &success);
5066
if (!success)
5067
return false;
5068
5069
std::optional<RegisterInfo> data_reg =
5070
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i);
5071
context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
5072
offset + addr_byte_size);
5073
if (!MemAWrite(context, address + offset, data, addr_byte_size))
5074
return false;
5075
}
5076
5077
// address = address + 4;
5078
offset += addr_byte_size;
5079
}
5080
}
5081
5082
// if registers<15> == '1' then
5083
// MemA[address,4] = PCStoreValue();
5084
if (BitIsSet(registers, 15)) {
5085
std::optional<RegisterInfo> pc_reg =
5086
GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);
5087
context.SetRegisterPlusOffset(*pc_reg, 8);
5088
const uint32_t pc = ReadCoreReg(PC_REG, &success);
5089
if (!success)
5090
return false;
5091
5092
if (!MemAWrite(context, address + offset, pc, addr_byte_size))
5093
return false;
5094
}
5095
5096
// if wback then R[n] = R[n] + 4*BitCount(registers);
5097
if (wback) {
5098
offset = addr_byte_size * BitCount(registers);
5099
context.type = EmulateInstruction::eContextAdjustBaseRegister;
5100
context.SetImmediateSigned(offset);
5101
addr_t data = Rn + offset;
5102
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5103
data))
5104
return false;
5105
}
5106
}
5107
return true;
5108
}
5109
5110
// STR (store immediate) calculates an address from a base register value and an
5111
// immediate offset, and stores a word
5112
// from a register to memory. It can use offset, post-indexed, or pre-indexed
5113
// addressing.
5114
bool EmulateInstructionARM::EmulateSTRThumb(const uint32_t opcode,
5115
const ARMEncoding encoding) {
5116
#if 0
5117
if ConditionPassed() then
5118
EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5119
offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5120
address = if index then offset_addr else R[n];
5121
if UnalignedSupport() || address<1:0> == '00' then
5122
MemU[address,4] = R[t];
5123
else // Can only occur before ARMv7
5124
MemU[address,4] = bits(32) UNKNOWN;
5125
if wback then R[n] = offset_addr;
5126
#endif
5127
5128
bool success = false;
5129
5130
if (ConditionPassed(opcode)) {
5131
const uint32_t addr_byte_size = GetAddressByteSize();
5132
5133
uint32_t t;
5134
uint32_t n;
5135
uint32_t imm32;
5136
bool index;
5137
bool add;
5138
bool wback;
5139
// EncodingSpecificOperations (); NullCheckIfThumbEE(n);
5140
switch (encoding) {
5141
case eEncodingT1:
5142
// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
5143
t = Bits32(opcode, 2, 0);
5144
n = Bits32(opcode, 5, 3);
5145
imm32 = Bits32(opcode, 10, 6) << 2;
5146
5147
// index = TRUE; add = TRUE; wback = FALSE;
5148
index = true;
5149
add = false;
5150
wback = false;
5151
break;
5152
5153
case eEncodingT2:
5154
// t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
5155
t = Bits32(opcode, 10, 8);
5156
n = 13;
5157
imm32 = Bits32(opcode, 7, 0) << 2;
5158
5159
// index = TRUE; add = TRUE; wback = FALSE;
5160
index = true;
5161
add = true;
5162
wback = false;
5163
break;
5164
5165
case eEncodingT3:
5166
// if Rn == '1111' then UNDEFINED;
5167
if (Bits32(opcode, 19, 16) == 15)
5168
return false;
5169
5170
// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5171
t = Bits32(opcode, 15, 12);
5172
n = Bits32(opcode, 19, 16);
5173
imm32 = Bits32(opcode, 11, 0);
5174
5175
// index = TRUE; add = TRUE; wback = FALSE;
5176
index = true;
5177
add = true;
5178
wback = false;
5179
5180
// if t == 15 then UNPREDICTABLE;
5181
if (t == 15)
5182
return false;
5183
break;
5184
5185
case eEncodingT4:
5186
// if P == '1' && U == '1' && W == '0' then SEE STRT;
5187
// if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 ==
5188
// '00000100' then SEE PUSH;
5189
// if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
5190
if ((Bits32(opcode, 19, 16) == 15) ||
5191
(BitIsClear(opcode, 10) && BitIsClear(opcode, 8)))
5192
return false;
5193
5194
// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5195
t = Bits32(opcode, 15, 12);
5196
n = Bits32(opcode, 19, 16);
5197
imm32 = Bits32(opcode, 7, 0);
5198
5199
// index = (P == '1'); add = (U == '1'); wback = (W == '1');
5200
index = BitIsSet(opcode, 10);
5201
add = BitIsSet(opcode, 9);
5202
wback = BitIsSet(opcode, 8);
5203
5204
// if t == 15 || (wback && n == t) then UNPREDICTABLE;
5205
if ((t == 15) || (wback && (n == t)))
5206
return false;
5207
break;
5208
5209
default:
5210
return false;
5211
}
5212
5213
addr_t offset_addr;
5214
addr_t address;
5215
5216
// offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5217
uint32_t base_address = ReadCoreReg(n, &success);
5218
if (!success)
5219
return false;
5220
5221
if (add)
5222
offset_addr = base_address + imm32;
5223
else
5224
offset_addr = base_address - imm32;
5225
5226
// address = if index then offset_addr else R[n];
5227
if (index)
5228
address = offset_addr;
5229
else
5230
address = base_address;
5231
5232
EmulateInstruction::Context context;
5233
if (n == 13)
5234
context.type = eContextPushRegisterOnStack;
5235
else
5236
context.type = eContextRegisterStore;
5237
5238
std::optional<RegisterInfo> base_reg =
5239
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
5240
5241
// if UnalignedSupport() || address<1:0> == '00' then
5242
if (UnalignedSupport() ||
5243
(BitIsClear(address, 1) && BitIsClear(address, 0))) {
5244
// MemU[address,4] = R[t];
5245
uint32_t data =
5246
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
5247
if (!success)
5248
return false;
5249
5250
std::optional<RegisterInfo> data_reg =
5251
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
5252
int32_t offset = address - base_address;
5253
context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, offset);
5254
if (!MemUWrite(context, address, data, addr_byte_size))
5255
return false;
5256
} else {
5257
// MemU[address,4] = bits(32) UNKNOWN;
5258
WriteBits32UnknownToMemory(address);
5259
}
5260
5261
// if wback then R[n] = offset_addr;
5262
if (wback) {
5263
if (n == 13)
5264
context.type = eContextAdjustStackPointer;
5265
else
5266
context.type = eContextAdjustBaseRegister;
5267
context.SetAddress(offset_addr);
5268
5269
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5270
offset_addr))
5271
return false;
5272
}
5273
}
5274
return true;
5275
}
5276
5277
// STR (Store Register) calculates an address from a base register value and an
5278
// offset register value, stores a
5279
// word from a register to memory. The offset register value can optionally
5280
// be shifted.
5281
bool EmulateInstructionARM::EmulateSTRRegister(const uint32_t opcode,
5282
const ARMEncoding encoding) {
5283
#if 0
5284
if ConditionPassed() then
5285
EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5286
offset = Shift(R[m], shift_t, shift_n, APSR.C);
5287
offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5288
address = if index then offset_addr else R[n];
5289
if t == 15 then // Only possible for encoding A1
5290
data = PCStoreValue();
5291
else
5292
data = R[t];
5293
if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
5294
MemU[address,4] = data;
5295
else // Can only occur before ARMv7
5296
MemU[address,4] = bits(32) UNKNOWN;
5297
if wback then R[n] = offset_addr;
5298
#endif
5299
5300
bool success = false;
5301
5302
if (ConditionPassed(opcode)) {
5303
const uint32_t addr_byte_size = GetAddressByteSize();
5304
5305
uint32_t t;
5306
uint32_t n;
5307
uint32_t m;
5308
ARM_ShifterType shift_t;
5309
uint32_t shift_n;
5310
bool index;
5311
bool add;
5312
bool wback;
5313
5314
// EncodingSpecificOperations (); NullCheckIfThumbEE(n);
5315
switch (encoding) {
5316
case eEncodingT1:
5317
// if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
5318
// in ThumbEE";
5319
// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5320
t = Bits32(opcode, 2, 0);
5321
n = Bits32(opcode, 5, 3);
5322
m = Bits32(opcode, 8, 6);
5323
5324
// index = TRUE; add = TRUE; wback = FALSE;
5325
index = true;
5326
add = true;
5327
wback = false;
5328
5329
// (shift_t, shift_n) = (SRType_LSL, 0);
5330
shift_t = SRType_LSL;
5331
shift_n = 0;
5332
break;
5333
5334
case eEncodingT2:
5335
// if Rn == '1111' then UNDEFINED;
5336
if (Bits32(opcode, 19, 16) == 15)
5337
return false;
5338
5339
// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5340
t = Bits32(opcode, 15, 12);
5341
n = Bits32(opcode, 19, 16);
5342
m = Bits32(opcode, 3, 0);
5343
5344
// index = TRUE; add = TRUE; wback = FALSE;
5345
index = true;
5346
add = true;
5347
wback = false;
5348
5349
// (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5350
shift_t = SRType_LSL;
5351
shift_n = Bits32(opcode, 5, 4);
5352
5353
// if t == 15 || BadReg(m) then UNPREDICTABLE;
5354
if ((t == 15) || (BadReg(m)))
5355
return false;
5356
break;
5357
5358
case eEncodingA1: {
5359
// if P == '0' && W == '1' then SEE STRT;
5360
// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5361
t = Bits32(opcode, 15, 12);
5362
n = Bits32(opcode, 19, 16);
5363
m = Bits32(opcode, 3, 0);
5364
5365
// index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
5366
// (W == '1');
5367
index = BitIsSet(opcode, 24);
5368
add = BitIsSet(opcode, 23);
5369
wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
5370
5371
// (shift_t, shift_n) = DecodeImmShift(type, imm5);
5372
uint32_t typ = Bits32(opcode, 6, 5);
5373
uint32_t imm5 = Bits32(opcode, 11, 7);
5374
shift_n = DecodeImmShift(typ, imm5, shift_t);
5375
5376
// if m == 15 then UNPREDICTABLE;
5377
if (m == 15)
5378
return false;
5379
5380
// if wback && (n == 15 || n == t) then UNPREDICTABLE;
5381
if (wback && ((n == 15) || (n == t)))
5382
return false;
5383
5384
break;
5385
}
5386
default:
5387
return false;
5388
}
5389
5390
addr_t offset_addr;
5391
addr_t address;
5392
int32_t offset = 0;
5393
5394
addr_t base_address =
5395
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5396
if (!success)
5397
return false;
5398
5399
uint32_t Rm_data =
5400
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5401
if (!success)
5402
return false;
5403
5404
// offset = Shift(R[m], shift_t, shift_n, APSR.C);
5405
offset = Shift(Rm_data, shift_t, shift_n, APSR_C, &success);
5406
if (!success)
5407
return false;
5408
5409
// offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5410
if (add)
5411
offset_addr = base_address + offset;
5412
else
5413
offset_addr = base_address - offset;
5414
5415
// address = if index then offset_addr else R[n];
5416
if (index)
5417
address = offset_addr;
5418
else
5419
address = base_address;
5420
5421
uint32_t data;
5422
// if t == 15 then // Only possible for encoding A1
5423
if (t == 15)
5424
// data = PCStoreValue();
5425
data = ReadCoreReg(PC_REG, &success);
5426
else
5427
// data = R[t];
5428
data =
5429
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
5430
5431
if (!success)
5432
return false;
5433
5434
EmulateInstruction::Context context;
5435
context.type = eContextRegisterStore;
5436
5437
// if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() ==
5438
// InstrSet_ARM then
5439
if (UnalignedSupport() ||
5440
(BitIsClear(address, 1) && BitIsClear(address, 0)) ||
5441
CurrentInstrSet() == eModeARM) {
5442
// MemU[address,4] = data;
5443
5444
std::optional<RegisterInfo> base_reg =
5445
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
5446
std::optional<RegisterInfo> data_reg =
5447
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
5448
5449
context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
5450
address - base_address);
5451
if (!MemUWrite(context, address, data, addr_byte_size))
5452
return false;
5453
5454
} else
5455
// MemU[address,4] = bits(32) UNKNOWN;
5456
WriteBits32UnknownToMemory(address);
5457
5458
// if wback then R[n] = offset_addr;
5459
if (wback) {
5460
context.type = eContextRegisterLoad;
5461
context.SetAddress(offset_addr);
5462
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5463
offset_addr))
5464
return false;
5465
}
5466
}
5467
return true;
5468
}
5469
5470
bool EmulateInstructionARM::EmulateSTRBThumb(const uint32_t opcode,
5471
const ARMEncoding encoding) {
5472
#if 0
5473
if ConditionPassed() then
5474
EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5475
offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5476
address = if index then offset_addr else R[n];
5477
MemU[address,1] = R[t]<7:0>;
5478
if wback then R[n] = offset_addr;
5479
#endif
5480
5481
bool success = false;
5482
5483
if (ConditionPassed(opcode)) {
5484
uint32_t t;
5485
uint32_t n;
5486
uint32_t imm32;
5487
bool index;
5488
bool add;
5489
bool wback;
5490
// EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5491
switch (encoding) {
5492
case eEncodingT1:
5493
// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5494
t = Bits32(opcode, 2, 0);
5495
n = Bits32(opcode, 5, 3);
5496
imm32 = Bits32(opcode, 10, 6);
5497
5498
// index = TRUE; add = TRUE; wback = FALSE;
5499
index = true;
5500
add = true;
5501
wback = false;
5502
break;
5503
5504
case eEncodingT2:
5505
// if Rn == '1111' then UNDEFINED;
5506
if (Bits32(opcode, 19, 16) == 15)
5507
return false;
5508
5509
// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5510
t = Bits32(opcode, 15, 12);
5511
n = Bits32(opcode, 19, 16);
5512
imm32 = Bits32(opcode, 11, 0);
5513
5514
// index = TRUE; add = TRUE; wback = FALSE;
5515
index = true;
5516
add = true;
5517
wback = false;
5518
5519
// if BadReg(t) then UNPREDICTABLE;
5520
if (BadReg(t))
5521
return false;
5522
break;
5523
5524
case eEncodingT3:
5525
// if P == '1' && U == '1' && W == '0' then SEE STRBT;
5526
// if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
5527
if (Bits32(opcode, 19, 16) == 15)
5528
return false;
5529
5530
// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5531
t = Bits32(opcode, 15, 12);
5532
n = Bits32(opcode, 19, 16);
5533
imm32 = Bits32(opcode, 7, 0);
5534
5535
// index = (P == '1'); add = (U == '1'); wback = (W == '1');
5536
index = BitIsSet(opcode, 10);
5537
add = BitIsSet(opcode, 9);
5538
wback = BitIsSet(opcode, 8);
5539
5540
// if BadReg(t) || (wback && n == t) then UNPREDICTABLE
5541
if ((BadReg(t)) || (wback && (n == t)))
5542
return false;
5543
break;
5544
5545
default:
5546
return false;
5547
}
5548
5549
addr_t offset_addr;
5550
addr_t address;
5551
addr_t base_address =
5552
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5553
if (!success)
5554
return false;
5555
5556
// offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5557
if (add)
5558
offset_addr = base_address + imm32;
5559
else
5560
offset_addr = base_address - imm32;
5561
5562
// address = if index then offset_addr else R[n];
5563
if (index)
5564
address = offset_addr;
5565
else
5566
address = base_address;
5567
5568
// MemU[address,1] = R[t]<7:0>
5569
std::optional<RegisterInfo> base_reg =
5570
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
5571
std::optional<RegisterInfo> data_reg =
5572
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
5573
5574
EmulateInstruction::Context context;
5575
context.type = eContextRegisterStore;
5576
context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
5577
address - base_address);
5578
5579
uint32_t data =
5580
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
5581
if (!success)
5582
return false;
5583
5584
data = Bits32(data, 7, 0);
5585
5586
if (!MemUWrite(context, address, data, 1))
5587
return false;
5588
5589
// if wback then R[n] = offset_addr;
5590
if (wback) {
5591
context.type = eContextRegisterLoad;
5592
context.SetAddress(offset_addr);
5593
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5594
offset_addr))
5595
return false;
5596
}
5597
}
5598
5599
return true;
5600
}
5601
5602
// STRH (register) calculates an address from a base register value and an
5603
// offset register value, and stores a
5604
// halfword from a register to memory. The offset register value can be
5605
// shifted left by 0, 1, 2, or 3 bits.
5606
bool EmulateInstructionARM::EmulateSTRHRegister(const uint32_t opcode,
5607
const ARMEncoding encoding) {
5608
#if 0
5609
if ConditionPassed() then
5610
EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5611
offset = Shift(R[m], shift_t, shift_n, APSR.C);
5612
offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5613
address = if index then offset_addr else R[n];
5614
if UnalignedSupport() || address<0> == '0' then
5615
MemU[address,2] = R[t]<15:0>;
5616
else // Can only occur before ARMv7
5617
MemU[address,2] = bits(16) UNKNOWN;
5618
if wback then R[n] = offset_addr;
5619
#endif
5620
5621
bool success = false;
5622
5623
if (ConditionPassed(opcode)) {
5624
uint32_t t;
5625
uint32_t n;
5626
uint32_t m;
5627
bool index;
5628
bool add;
5629
bool wback;
5630
ARM_ShifterType shift_t;
5631
uint32_t shift_n;
5632
5633
// EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5634
switch (encoding) {
5635
case eEncodingT1:
5636
// if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
5637
// in ThumbEE";
5638
// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5639
t = Bits32(opcode, 2, 0);
5640
n = Bits32(opcode, 5, 3);
5641
m = Bits32(opcode, 8, 6);
5642
5643
// index = TRUE; add = TRUE; wback = FALSE;
5644
index = true;
5645
add = true;
5646
wback = false;
5647
5648
// (shift_t, shift_n) = (SRType_LSL, 0);
5649
shift_t = SRType_LSL;
5650
shift_n = 0;
5651
5652
break;
5653
5654
case eEncodingT2:
5655
// if Rn == '1111' then UNDEFINED;
5656
// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5657
t = Bits32(opcode, 15, 12);
5658
n = Bits32(opcode, 19, 16);
5659
m = Bits32(opcode, 3, 0);
5660
if (n == 15)
5661
return false;
5662
5663
// index = TRUE; add = TRUE; wback = FALSE;
5664
index = true;
5665
add = true;
5666
wback = false;
5667
5668
// (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5669
shift_t = SRType_LSL;
5670
shift_n = Bits32(opcode, 5, 4);
5671
5672
// if BadReg(t) || BadReg(m) then UNPREDICTABLE;
5673
if (BadReg(t) || BadReg(m))
5674
return false;
5675
5676
break;
5677
5678
case eEncodingA1:
5679
// if P == '0' && W == '1' then SEE STRHT;
5680
// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5681
t = Bits32(opcode, 15, 12);
5682
n = Bits32(opcode, 19, 16);
5683
m = Bits32(opcode, 3, 0);
5684
5685
// index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
5686
// (W == '1');
5687
index = BitIsSet(opcode, 24);
5688
add = BitIsSet(opcode, 23);
5689
wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
5690
5691
// (shift_t, shift_n) = (SRType_LSL, 0);
5692
shift_t = SRType_LSL;
5693
shift_n = 0;
5694
5695
// if t == 15 || m == 15 then UNPREDICTABLE;
5696
if ((t == 15) || (m == 15))
5697
return false;
5698
5699
// if wback && (n == 15 || n == t) then UNPREDICTABLE;
5700
if (wback && ((n == 15) || (n == t)))
5701
return false;
5702
5703
break;
5704
5705
default:
5706
return false;
5707
}
5708
5709
uint32_t Rm = ReadCoreReg(m, &success);
5710
if (!success)
5711
return false;
5712
5713
uint32_t Rn = ReadCoreReg(n, &success);
5714
if (!success)
5715
return false;
5716
5717
// offset = Shift(R[m], shift_t, shift_n, APSR.C);
5718
uint32_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
5719
if (!success)
5720
return false;
5721
5722
// offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5723
addr_t offset_addr;
5724
if (add)
5725
offset_addr = Rn + offset;
5726
else
5727
offset_addr = Rn - offset;
5728
5729
// address = if index then offset_addr else R[n];
5730
addr_t address;
5731
if (index)
5732
address = offset_addr;
5733
else
5734
address = Rn;
5735
5736
EmulateInstruction::Context context;
5737
context.type = eContextRegisterStore;
5738
5739
// if UnalignedSupport() || address<0> == '0' then
5740
if (UnalignedSupport() || BitIsClear(address, 0)) {
5741
// MemU[address,2] = R[t]<15:0>;
5742
uint32_t Rt = ReadCoreReg(t, &success);
5743
if (!success)
5744
return false;
5745
5746
EmulateInstruction::Context context;
5747
context.type = eContextRegisterStore;
5748
std::optional<RegisterInfo> base_reg =
5749
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
5750
std::optional<RegisterInfo> offset_reg =
5751
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
5752
std::optional<RegisterInfo> data_reg =
5753
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
5754
context.SetRegisterToRegisterPlusIndirectOffset(*base_reg, *offset_reg,
5755
*data_reg);
5756
5757
if (!MemUWrite(context, address, Bits32(Rt, 15, 0), 2))
5758
return false;
5759
} else // Can only occur before ARMv7
5760
{
5761
// MemU[address,2] = bits(16) UNKNOWN;
5762
}
5763
5764
// if wback then R[n] = offset_addr;
5765
if (wback) {
5766
context.type = eContextAdjustBaseRegister;
5767
context.SetAddress(offset_addr);
5768
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5769
offset_addr))
5770
return false;
5771
}
5772
}
5773
5774
return true;
5775
}
5776
5777
// Add with Carry (immediate) adds an immediate value and the carry flag value
5778
// to a register value, and writes the result to the destination register. It
5779
// can optionally update the condition flags based on the result.
5780
bool EmulateInstructionARM::EmulateADCImm(const uint32_t opcode,
5781
const ARMEncoding encoding) {
5782
#if 0
5783
// ARM pseudo code...
5784
if ConditionPassed() then
5785
EncodingSpecificOperations();
5786
(result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5787
if d == 15 then // Can only occur for ARM encoding
5788
ALUWritePC(result); // setflags is always FALSE here
5789
else
5790
R[d] = result;
5791
if setflags then
5792
APSR.N = result<31>;
5793
APSR.Z = IsZeroBit(result);
5794
APSR.C = carry;
5795
APSR.V = overflow;
5796
#endif
5797
5798
bool success = false;
5799
5800
if (ConditionPassed(opcode)) {
5801
uint32_t Rd, Rn;
5802
uint32_t
5803
imm32; // the immediate value to be added to the value obtained from Rn
5804
bool setflags;
5805
switch (encoding) {
5806
case eEncodingT1:
5807
Rd = Bits32(opcode, 11, 8);
5808
Rn = Bits32(opcode, 19, 16);
5809
setflags = BitIsSet(opcode, 20);
5810
imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5811
if (BadReg(Rd) || BadReg(Rn))
5812
return false;
5813
break;
5814
case eEncodingA1:
5815
Rd = Bits32(opcode, 15, 12);
5816
Rn = Bits32(opcode, 19, 16);
5817
setflags = BitIsSet(opcode, 20);
5818
imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5819
5820
if (Rd == 15 && setflags)
5821
return EmulateSUBSPcLrEtc(opcode, encoding);
5822
break;
5823
default:
5824
return false;
5825
}
5826
5827
// Read the first operand.
5828
int32_t val1 = ReadCoreReg(Rn, &success);
5829
if (!success)
5830
return false;
5831
5832
AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5833
5834
EmulateInstruction::Context context;
5835
context.type = EmulateInstruction::eContextImmediate;
5836
context.SetNoArgs();
5837
5838
if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
5839
res.carry_out, res.overflow))
5840
return false;
5841
}
5842
return true;
5843
}
5844
5845
// Add with Carry (register) adds a register value, the carry flag value, and
5846
// an optionally-shifted register value, and writes the result to the
5847
// destination register. It can optionally update the condition flags based on
5848
// the result.
5849
bool EmulateInstructionARM::EmulateADCReg(const uint32_t opcode,
5850
const ARMEncoding encoding) {
5851
#if 0
5852
// ARM pseudo code...
5853
if ConditionPassed() then
5854
EncodingSpecificOperations();
5855
shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5856
(result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5857
if d == 15 then // Can only occur for ARM encoding
5858
ALUWritePC(result); // setflags is always FALSE here
5859
else
5860
R[d] = result;
5861
if setflags then
5862
APSR.N = result<31>;
5863
APSR.Z = IsZeroBit(result);
5864
APSR.C = carry;
5865
APSR.V = overflow;
5866
#endif
5867
5868
bool success = false;
5869
5870
if (ConditionPassed(opcode)) {
5871
uint32_t Rd, Rn, Rm;
5872
ARM_ShifterType shift_t;
5873
uint32_t shift_n; // the shift applied to the value read from Rm
5874
bool setflags;
5875
switch (encoding) {
5876
case eEncodingT1:
5877
Rd = Rn = Bits32(opcode, 2, 0);
5878
Rm = Bits32(opcode, 5, 3);
5879
setflags = !InITBlock();
5880
shift_t = SRType_LSL;
5881
shift_n = 0;
5882
break;
5883
case eEncodingT2:
5884
Rd = Bits32(opcode, 11, 8);
5885
Rn = Bits32(opcode, 19, 16);
5886
Rm = Bits32(opcode, 3, 0);
5887
setflags = BitIsSet(opcode, 20);
5888
shift_n = DecodeImmShiftThumb(opcode, shift_t);
5889
if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5890
return false;
5891
break;
5892
case eEncodingA1:
5893
Rd = Bits32(opcode, 15, 12);
5894
Rn = Bits32(opcode, 19, 16);
5895
Rm = Bits32(opcode, 3, 0);
5896
setflags = BitIsSet(opcode, 20);
5897
shift_n = DecodeImmShiftARM(opcode, shift_t);
5898
5899
if (Rd == 15 && setflags)
5900
return EmulateSUBSPcLrEtc(opcode, encoding);
5901
break;
5902
default:
5903
return false;
5904
}
5905
5906
// Read the first operand.
5907
int32_t val1 = ReadCoreReg(Rn, &success);
5908
if (!success)
5909
return false;
5910
5911
// Read the second operand.
5912
int32_t val2 = ReadCoreReg(Rm, &success);
5913
if (!success)
5914
return false;
5915
5916
uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
5917
if (!success)
5918
return false;
5919
AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5920
5921
EmulateInstruction::Context context;
5922
context.type = EmulateInstruction::eContextImmediate;
5923
context.SetNoArgs();
5924
5925
if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
5926
res.carry_out, res.overflow))
5927
return false;
5928
}
5929
return true;
5930
}
5931
5932
// This instruction adds an immediate value to the PC value to form a PC-
5933
// relative address, and writes the result to the destination register.
5934
bool EmulateInstructionARM::EmulateADR(const uint32_t opcode,
5935
const ARMEncoding encoding) {
5936
#if 0
5937
// ARM pseudo code...
5938
if ConditionPassed() then
5939
EncodingSpecificOperations();
5940
result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5941
if d == 15 then // Can only occur for ARM encodings
5942
ALUWritePC(result);
5943
else
5944
R[d] = result;
5945
#endif
5946
5947
bool success = false;
5948
5949
if (ConditionPassed(opcode)) {
5950
uint32_t Rd;
5951
uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5952
bool add;
5953
switch (encoding) {
5954
case eEncodingT1:
5955
Rd = Bits32(opcode, 10, 8);
5956
imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5957
add = true;
5958
break;
5959
case eEncodingT2:
5960
case eEncodingT3:
5961
Rd = Bits32(opcode, 11, 8);
5962
imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5963
add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5964
if (BadReg(Rd))
5965
return false;
5966
break;
5967
case eEncodingA1:
5968
case eEncodingA2:
5969
Rd = Bits32(opcode, 15, 12);
5970
imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5971
add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5972
break;
5973
default:
5974
return false;
5975
}
5976
5977
// Read the PC value.
5978
uint32_t pc = ReadCoreReg(PC_REG, &success);
5979
if (!success)
5980
return false;
5981
5982
uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5983
5984
EmulateInstruction::Context context;
5985
context.type = EmulateInstruction::eContextImmediate;
5986
context.SetNoArgs();
5987
5988
if (!WriteCoreReg(context, result, Rd))
5989
return false;
5990
}
5991
return true;
5992
}
5993
5994
// This instruction performs a bitwise AND of a register value and an immediate
5995
// value, and writes the result to the destination register. It can optionally
5996
// update the condition flags based on the result.
5997
bool EmulateInstructionARM::EmulateANDImm(const uint32_t opcode,
5998
const ARMEncoding encoding) {
5999
#if 0
6000
// ARM pseudo code...
6001
if ConditionPassed() then
6002
EncodingSpecificOperations();
6003
result = R[n] AND imm32;
6004
if d == 15 then // Can only occur for ARM encoding
6005
ALUWritePC(result); // setflags is always FALSE here
6006
else
6007
R[d] = result;
6008
if setflags then
6009
APSR.N = result<31>;
6010
APSR.Z = IsZeroBit(result);
6011
APSR.C = carry;
6012
// APSR.V unchanged
6013
#endif
6014
6015
bool success = false;
6016
6017
if (ConditionPassed(opcode)) {
6018
uint32_t Rd, Rn;
6019
uint32_t
6020
imm32; // the immediate value to be ANDed to the value obtained from Rn
6021
bool setflags;
6022
uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6023
switch (encoding) {
6024
case eEncodingT1:
6025
Rd = Bits32(opcode, 11, 8);
6026
Rn = Bits32(opcode, 19, 16);
6027
setflags = BitIsSet(opcode, 20);
6028
imm32 = ThumbExpandImm_C(
6029
opcode, APSR_C,
6030
carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6031
// if Rd == '1111' && S == '1' then SEE TST (immediate);
6032
if (Rd == 15 && setflags)
6033
return EmulateTSTImm(opcode, eEncodingT1);
6034
if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
6035
return false;
6036
break;
6037
case eEncodingA1:
6038
Rd = Bits32(opcode, 15, 12);
6039
Rn = Bits32(opcode, 19, 16);
6040
setflags = BitIsSet(opcode, 20);
6041
imm32 =
6042
ARMExpandImm_C(opcode, APSR_C,
6043
carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6044
6045
if (Rd == 15 && setflags)
6046
return EmulateSUBSPcLrEtc(opcode, encoding);
6047
break;
6048
default:
6049
return false;
6050
}
6051
6052
// Read the first operand.
6053
uint32_t val1 = ReadCoreReg(Rn, &success);
6054
if (!success)
6055
return false;
6056
6057
uint32_t result = val1 & imm32;
6058
6059
EmulateInstruction::Context context;
6060
context.type = EmulateInstruction::eContextImmediate;
6061
context.SetNoArgs();
6062
6063
if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6064
return false;
6065
}
6066
return true;
6067
}
6068
6069
// This instruction performs a bitwise AND of a register value and an
6070
// optionally-shifted register value, and writes the result to the destination
6071
// register. It can optionally update the condition flags based on the result.
6072
bool EmulateInstructionARM::EmulateANDReg(const uint32_t opcode,
6073
const ARMEncoding encoding) {
6074
#if 0
6075
// ARM pseudo code...
6076
if ConditionPassed() then
6077
EncodingSpecificOperations();
6078
(shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6079
result = R[n] AND shifted;
6080
if d == 15 then // Can only occur for ARM encoding
6081
ALUWritePC(result); // setflags is always FALSE here
6082
else
6083
R[d] = result;
6084
if setflags then
6085
APSR.N = result<31>;
6086
APSR.Z = IsZeroBit(result);
6087
APSR.C = carry;
6088
// APSR.V unchanged
6089
#endif
6090
6091
bool success = false;
6092
6093
if (ConditionPassed(opcode)) {
6094
uint32_t Rd, Rn, Rm;
6095
ARM_ShifterType shift_t;
6096
uint32_t shift_n; // the shift applied to the value read from Rm
6097
bool setflags;
6098
uint32_t carry;
6099
switch (encoding) {
6100
case eEncodingT1:
6101
Rd = Rn = Bits32(opcode, 2, 0);
6102
Rm = Bits32(opcode, 5, 3);
6103
setflags = !InITBlock();
6104
shift_t = SRType_LSL;
6105
shift_n = 0;
6106
break;
6107
case eEncodingT2:
6108
Rd = Bits32(opcode, 11, 8);
6109
Rn = Bits32(opcode, 19, 16);
6110
Rm = Bits32(opcode, 3, 0);
6111
setflags = BitIsSet(opcode, 20);
6112
shift_n = DecodeImmShiftThumb(opcode, shift_t);
6113
// if Rd == '1111' && S == '1' then SEE TST (register);
6114
if (Rd == 15 && setflags)
6115
return EmulateTSTReg(opcode, eEncodingT2);
6116
if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
6117
return false;
6118
break;
6119
case eEncodingA1:
6120
Rd = Bits32(opcode, 15, 12);
6121
Rn = Bits32(opcode, 19, 16);
6122
Rm = Bits32(opcode, 3, 0);
6123
setflags = BitIsSet(opcode, 20);
6124
shift_n = DecodeImmShiftARM(opcode, shift_t);
6125
6126
if (Rd == 15 && setflags)
6127
return EmulateSUBSPcLrEtc(opcode, encoding);
6128
break;
6129
default:
6130
return false;
6131
}
6132
6133
// Read the first operand.
6134
uint32_t val1 = ReadCoreReg(Rn, &success);
6135
if (!success)
6136
return false;
6137
6138
// Read the second operand.
6139
uint32_t val2 = ReadCoreReg(Rm, &success);
6140
if (!success)
6141
return false;
6142
6143
uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
6144
if (!success)
6145
return false;
6146
uint32_t result = val1 & shifted;
6147
6148
EmulateInstruction::Context context;
6149
context.type = EmulateInstruction::eContextImmediate;
6150
context.SetNoArgs();
6151
6152
if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6153
return false;
6154
}
6155
return true;
6156
}
6157
6158
// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and
6159
// the complement of an immediate value, and writes the result to the
6160
// destination register. It can optionally update the condition flags based on
6161
// the result.
6162
bool EmulateInstructionARM::EmulateBICImm(const uint32_t opcode,
6163
const ARMEncoding encoding) {
6164
#if 0
6165
// ARM pseudo code...
6166
if ConditionPassed() then
6167
EncodingSpecificOperations();
6168
result = R[n] AND NOT(imm32);
6169
if d == 15 then // Can only occur for ARM encoding
6170
ALUWritePC(result); // setflags is always FALSE here
6171
else
6172
R[d] = result;
6173
if setflags then
6174
APSR.N = result<31>;
6175
APSR.Z = IsZeroBit(result);
6176
APSR.C = carry;
6177
// APSR.V unchanged
6178
#endif
6179
6180
bool success = false;
6181
6182
if (ConditionPassed(opcode)) {
6183
uint32_t Rd, Rn;
6184
uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to
6185
// the value obtained from Rn
6186
bool setflags;
6187
uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6188
switch (encoding) {
6189
case eEncodingT1:
6190
Rd = Bits32(opcode, 11, 8);
6191
Rn = Bits32(opcode, 19, 16);
6192
setflags = BitIsSet(opcode, 20);
6193
imm32 = ThumbExpandImm_C(
6194
opcode, APSR_C,
6195
carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6196
if (BadReg(Rd) || BadReg(Rn))
6197
return false;
6198
break;
6199
case eEncodingA1:
6200
Rd = Bits32(opcode, 15, 12);
6201
Rn = Bits32(opcode, 19, 16);
6202
setflags = BitIsSet(opcode, 20);
6203
imm32 =
6204
ARMExpandImm_C(opcode, APSR_C,
6205
carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6206
6207
// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
6208
// instructions;
6209
if (Rd == 15 && setflags)
6210
return EmulateSUBSPcLrEtc(opcode, encoding);
6211
break;
6212
default:
6213
return false;
6214
}
6215
6216
// Read the first operand.
6217
uint32_t val1 = ReadCoreReg(Rn, &success);
6218
if (!success)
6219
return false;
6220
6221
uint32_t result = val1 & ~imm32;
6222
6223
EmulateInstruction::Context context;
6224
context.type = EmulateInstruction::eContextImmediate;
6225
context.SetNoArgs();
6226
6227
if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6228
return false;
6229
}
6230
return true;
6231
}
6232
6233
// Bitwise Bit Clear (register) performs a bitwise AND of a register value and
6234
// the complement of an optionally-shifted register value, and writes the
6235
// result to the destination register. It can optionally update the condition
6236
// flags based on the result.
6237
bool EmulateInstructionARM::EmulateBICReg(const uint32_t opcode,
6238
const ARMEncoding encoding) {
6239
#if 0
6240
// ARM pseudo code...
6241
if ConditionPassed() then
6242
EncodingSpecificOperations();
6243
(shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6244
result = R[n] AND NOT(shifted);
6245
if d == 15 then // Can only occur for ARM encoding
6246
ALUWritePC(result); // setflags is always FALSE here
6247
else
6248
R[d] = result;
6249
if setflags then
6250
APSR.N = result<31>;
6251
APSR.Z = IsZeroBit(result);
6252
APSR.C = carry;
6253
// APSR.V unchanged
6254
#endif
6255
6256
bool success = false;
6257
6258
if (ConditionPassed(opcode)) {
6259
uint32_t Rd, Rn, Rm;
6260
ARM_ShifterType shift_t;
6261
uint32_t shift_n; // the shift applied to the value read from Rm
6262
bool setflags;
6263
uint32_t carry;
6264
switch (encoding) {
6265
case eEncodingT1:
6266
Rd = Rn = Bits32(opcode, 2, 0);
6267
Rm = Bits32(opcode, 5, 3);
6268
setflags = !InITBlock();
6269
shift_t = SRType_LSL;
6270
shift_n = 0;
6271
break;
6272
case eEncodingT2:
6273
Rd = Bits32(opcode, 11, 8);
6274
Rn = Bits32(opcode, 19, 16);
6275
Rm = Bits32(opcode, 3, 0);
6276
setflags = BitIsSet(opcode, 20);
6277
shift_n = DecodeImmShiftThumb(opcode, shift_t);
6278
if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
6279
return false;
6280
break;
6281
case eEncodingA1:
6282
Rd = Bits32(opcode, 15, 12);
6283
Rn = Bits32(opcode, 19, 16);
6284
Rm = Bits32(opcode, 3, 0);
6285
setflags = BitIsSet(opcode, 20);
6286
shift_n = DecodeImmShiftARM(opcode, shift_t);
6287
6288
// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
6289
// instructions;
6290
if (Rd == 15 && setflags)
6291
return EmulateSUBSPcLrEtc(opcode, encoding);
6292
break;
6293
default:
6294
return false;
6295
}
6296
6297
// Read the first operand.
6298
uint32_t val1 = ReadCoreReg(Rn, &success);
6299
if (!success)
6300
return false;
6301
6302
// Read the second operand.
6303
uint32_t val2 = ReadCoreReg(Rm, &success);
6304
if (!success)
6305
return false;
6306
6307
uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
6308
if (!success)
6309
return false;
6310
uint32_t result = val1 & ~shifted;
6311
6312
EmulateInstruction::Context context;
6313
context.type = EmulateInstruction::eContextImmediate;
6314
context.SetNoArgs();
6315
6316
if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6317
return false;
6318
}
6319
return true;
6320
}
6321
6322
// LDR (immediate, ARM) calculates an address from a base register value and an
6323
// immediate offset, loads a word
6324
// from memory, and writes it to a register. It can use offset, post-indexed,
6325
// or pre-indexed addressing.
6326
bool EmulateInstructionARM::EmulateLDRImmediateARM(const uint32_t opcode,
6327
const ARMEncoding encoding) {
6328
#if 0
6329
if ConditionPassed() then
6330
EncodingSpecificOperations();
6331
offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6332
address = if index then offset_addr else R[n];
6333
data = MemU[address,4];
6334
if wback then R[n] = offset_addr;
6335
if t == 15 then
6336
if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6337
elsif UnalignedSupport() || address<1:0> = '00' then
6338
R[t] = data;
6339
else // Can only apply before ARMv7
6340
R[t] = ROR(data, 8*UInt(address<1:0>));
6341
#endif
6342
6343
bool success = false;
6344
6345
if (ConditionPassed(opcode)) {
6346
const uint32_t addr_byte_size = GetAddressByteSize();
6347
6348
uint32_t t;
6349
uint32_t n;
6350
uint32_t imm32;
6351
bool index;
6352
bool add;
6353
bool wback;
6354
6355
switch (encoding) {
6356
case eEncodingA1:
6357
// if Rn == '1111' then SEE LDR (literal);
6358
// if P == '0' && W == '1' then SEE LDRT;
6359
// if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 ==
6360
// '000000000100' then SEE POP;
6361
// t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6362
t = Bits32(opcode, 15, 12);
6363
n = Bits32(opcode, 19, 16);
6364
imm32 = Bits32(opcode, 11, 0);
6365
6366
// index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6367
// (W == '1');
6368
index = BitIsSet(opcode, 24);
6369
add = BitIsSet(opcode, 23);
6370
wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
6371
6372
// if wback && n == t then UNPREDICTABLE;
6373
if (wback && (n == t))
6374
return false;
6375
6376
break;
6377
6378
default:
6379
return false;
6380
}
6381
6382
addr_t address;
6383
addr_t offset_addr;
6384
addr_t base_address = ReadCoreReg(n, &success);
6385
if (!success)
6386
return false;
6387
6388
// offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6389
if (add)
6390
offset_addr = base_address + imm32;
6391
else
6392
offset_addr = base_address - imm32;
6393
6394
// address = if index then offset_addr else R[n];
6395
if (index)
6396
address = offset_addr;
6397
else
6398
address = base_address;
6399
6400
// data = MemU[address,4];
6401
6402
std::optional<RegisterInfo> base_reg =
6403
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
6404
EmulateInstruction::Context context;
6405
context.type = eContextRegisterLoad;
6406
context.SetRegisterPlusOffset(*base_reg, address - base_address);
6407
6408
uint64_t data = MemURead(context, address, addr_byte_size, 0, &success);
6409
if (!success)
6410
return false;
6411
6412
// if wback then R[n] = offset_addr;
6413
if (wback) {
6414
context.type = eContextAdjustBaseRegister;
6415
context.SetAddress(offset_addr);
6416
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6417
offset_addr))
6418
return false;
6419
}
6420
6421
// if t == 15 then
6422
if (t == 15) {
6423
// if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6424
if (BitIsClear(address, 1) && BitIsClear(address, 0)) {
6425
// LoadWritePC (data);
6426
context.type = eContextRegisterLoad;
6427
context.SetRegisterPlusOffset(*base_reg, address - base_address);
6428
LoadWritePC(context, data);
6429
} else
6430
return false;
6431
}
6432
// elsif UnalignedSupport() || address<1:0> = '00' then
6433
else if (UnalignedSupport() ||
6434
(BitIsClear(address, 1) && BitIsClear(address, 0))) {
6435
// R[t] = data;
6436
context.type = eContextRegisterLoad;
6437
context.SetRegisterPlusOffset(*base_reg, address - base_address);
6438
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6439
data))
6440
return false;
6441
}
6442
// else // Can only apply before ARMv7
6443
else {
6444
// R[t] = ROR(data, 8*UInt(address<1:0>));
6445
data = ROR(data, Bits32(address, 1, 0), &success);
6446
if (!success)
6447
return false;
6448
context.type = eContextRegisterLoad;
6449
context.SetImmediate(data);
6450
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6451
data))
6452
return false;
6453
}
6454
}
6455
return true;
6456
}
6457
6458
// LDR (register) calculates an address from a base register value and an offset
6459
// register value, loads a word
6460
// from memory, and writes it to a register. The offset register value can
6461
// optionally be shifted.
6462
bool EmulateInstructionARM::EmulateLDRRegister(const uint32_t opcode,
6463
const ARMEncoding encoding) {
6464
#if 0
6465
if ConditionPassed() then
6466
EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6467
offset = Shift(R[m], shift_t, shift_n, APSR.C);
6468
offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6469
address = if index then offset_addr else R[n];
6470
data = MemU[address,4];
6471
if wback then R[n] = offset_addr;
6472
if t == 15 then
6473
if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6474
elsif UnalignedSupport() || address<1:0> = '00' then
6475
R[t] = data;
6476
else // Can only apply before ARMv7
6477
if CurrentInstrSet() == InstrSet_ARM then
6478
R[t] = ROR(data, 8*UInt(address<1:0>));
6479
else
6480
R[t] = bits(32) UNKNOWN;
6481
#endif
6482
6483
bool success = false;
6484
6485
if (ConditionPassed(opcode)) {
6486
const uint32_t addr_byte_size = GetAddressByteSize();
6487
6488
uint32_t t;
6489
uint32_t n;
6490
uint32_t m;
6491
bool index;
6492
bool add;
6493
bool wback;
6494
ARM_ShifterType shift_t;
6495
uint32_t shift_n;
6496
6497
switch (encoding) {
6498
case eEncodingT1:
6499
// if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
6500
// in ThumbEE";
6501
// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6502
t = Bits32(opcode, 2, 0);
6503
n = Bits32(opcode, 5, 3);
6504
m = Bits32(opcode, 8, 6);
6505
6506
// index = TRUE; add = TRUE; wback = FALSE;
6507
index = true;
6508
add = true;
6509
wback = false;
6510
6511
// (shift_t, shift_n) = (SRType_LSL, 0);
6512
shift_t = SRType_LSL;
6513
shift_n = 0;
6514
6515
break;
6516
6517
case eEncodingT2:
6518
// if Rn == '1111' then SEE LDR (literal);
6519
// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6520
t = Bits32(opcode, 15, 12);
6521
n = Bits32(opcode, 19, 16);
6522
m = Bits32(opcode, 3, 0);
6523
6524
// index = TRUE; add = TRUE; wback = FALSE;
6525
index = true;
6526
add = true;
6527
wback = false;
6528
6529
// (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6530
shift_t = SRType_LSL;
6531
shift_n = Bits32(opcode, 5, 4);
6532
6533
// if BadReg(m) then UNPREDICTABLE;
6534
if (BadReg(m))
6535
return false;
6536
6537
// if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
6538
if ((t == 15) && InITBlock() && !LastInITBlock())
6539
return false;
6540
6541
break;
6542
6543
case eEncodingA1: {
6544
// if P == '0' && W == '1' then SEE LDRT;
6545
// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6546
t = Bits32(opcode, 15, 12);
6547
n = Bits32(opcode, 19, 16);
6548
m = Bits32(opcode, 3, 0);
6549
6550
// index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6551
// (W == '1');
6552
index = BitIsSet(opcode, 24);
6553
add = BitIsSet(opcode, 23);
6554
wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
6555
6556
// (shift_t, shift_n) = DecodeImmShift(type, imm5);
6557
uint32_t type = Bits32(opcode, 6, 5);
6558
uint32_t imm5 = Bits32(opcode, 11, 7);
6559
shift_n = DecodeImmShift(type, imm5, shift_t);
6560
6561
// if m == 15 then UNPREDICTABLE;
6562
if (m == 15)
6563
return false;
6564
6565
// if wback && (n == 15 || n == t) then UNPREDICTABLE;
6566
if (wback && ((n == 15) || (n == t)))
6567
return false;
6568
} break;
6569
6570
default:
6571
return false;
6572
}
6573
6574
uint32_t Rm =
6575
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6576
if (!success)
6577
return false;
6578
6579
uint32_t Rn =
6580
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6581
if (!success)
6582
return false;
6583
6584
addr_t offset_addr;
6585
addr_t address;
6586
6587
// offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is
6588
// an application level alias for the CPSR".
6589
addr_t offset =
6590
Shift(Rm, shift_t, shift_n, Bit32(m_opcode_cpsr, APSR_C), &success);
6591
if (!success)
6592
return false;
6593
6594
// offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6595
if (add)
6596
offset_addr = Rn + offset;
6597
else
6598
offset_addr = Rn - offset;
6599
6600
// address = if index then offset_addr else R[n];
6601
if (index)
6602
address = offset_addr;
6603
else
6604
address = Rn;
6605
6606
// data = MemU[address,4];
6607
std::optional<RegisterInfo> base_reg =
6608
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
6609
EmulateInstruction::Context context;
6610
context.type = eContextRegisterLoad;
6611
context.SetRegisterPlusOffset(*base_reg, address - Rn);
6612
6613
uint64_t data = MemURead(context, address, addr_byte_size, 0, &success);
6614
if (!success)
6615
return false;
6616
6617
// if wback then R[n] = offset_addr;
6618
if (wback) {
6619
context.type = eContextAdjustBaseRegister;
6620
context.SetAddress(offset_addr);
6621
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6622
offset_addr))
6623
return false;
6624
}
6625
6626
// if t == 15 then
6627
if (t == 15) {
6628
// if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6629
if (BitIsClear(address, 1) && BitIsClear(address, 0)) {
6630
context.type = eContextRegisterLoad;
6631
context.SetRegisterPlusOffset(*base_reg, address - Rn);
6632
LoadWritePC(context, data);
6633
} else
6634
return false;
6635
}
6636
// elsif UnalignedSupport() || address<1:0> = '00' then
6637
else if (UnalignedSupport() ||
6638
(BitIsClear(address, 1) && BitIsClear(address, 0))) {
6639
// R[t] = data;
6640
context.type = eContextRegisterLoad;
6641
context.SetRegisterPlusOffset(*base_reg, address - Rn);
6642
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6643
data))
6644
return false;
6645
} else // Can only apply before ARMv7
6646
{
6647
// if CurrentInstrSet() == InstrSet_ARM then
6648
if (CurrentInstrSet() == eModeARM) {
6649
// R[t] = ROR(data, 8*UInt(address<1:0>));
6650
data = ROR(data, Bits32(address, 1, 0), &success);
6651
if (!success)
6652
return false;
6653
context.type = eContextRegisterLoad;
6654
context.SetImmediate(data);
6655
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6656
data))
6657
return false;
6658
} else {
6659
// R[t] = bits(32) UNKNOWN;
6660
WriteBits32Unknown(t);
6661
}
6662
}
6663
}
6664
return true;
6665
}
6666
6667
// LDRB (immediate, Thumb)
6668
bool EmulateInstructionARM::EmulateLDRBImmediate(const uint32_t opcode,
6669
const ARMEncoding encoding) {
6670
#if 0
6671
if ConditionPassed() then
6672
EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6673
offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6674
address = if index then offset_addr else R[n];
6675
R[t] = ZeroExtend(MemU[address,1], 32);
6676
if wback then R[n] = offset_addr;
6677
#endif
6678
6679
bool success = false;
6680
6681
if (ConditionPassed(opcode)) {
6682
uint32_t t;
6683
uint32_t n;
6684
uint32_t imm32;
6685
bool index;
6686
bool add;
6687
bool wback;
6688
6689
// EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6690
switch (encoding) {
6691
case eEncodingT1:
6692
// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6693
t = Bits32(opcode, 2, 0);
6694
n = Bits32(opcode, 5, 3);
6695
imm32 = Bits32(opcode, 10, 6);
6696
6697
// index = TRUE; add = TRUE; wback = FALSE;
6698
index = true;
6699
add = true;
6700
wback = false;
6701
6702
break;
6703
6704
case eEncodingT2:
6705
// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6706
t = Bits32(opcode, 15, 12);
6707
n = Bits32(opcode, 19, 16);
6708
imm32 = Bits32(opcode, 11, 0);
6709
6710
// index = TRUE; add = TRUE; wback = FALSE;
6711
index = true;
6712
add = true;
6713
wback = false;
6714
6715
// if Rt == '1111' then SEE PLD;
6716
if (t == 15)
6717
return false; // PLD is not implemented yet
6718
6719
// if Rn == '1111' then SEE LDRB (literal);
6720
if (n == 15)
6721
return EmulateLDRBLiteral(opcode, eEncodingT1);
6722
6723
// if t == 13 then UNPREDICTABLE;
6724
if (t == 13)
6725
return false;
6726
6727
break;
6728
6729
case eEncodingT3:
6730
// if P == '1' && U == '1' && W == '0' then SEE LDRBT;
6731
// if P == '0' && W == '0' then UNDEFINED;
6732
if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
6733
return false;
6734
6735
// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6736
t = Bits32(opcode, 15, 12);
6737
n = Bits32(opcode, 19, 16);
6738
imm32 = Bits32(opcode, 7, 0);
6739
6740
// index = (P == '1'); add = (U == '1'); wback = (W == '1');
6741
index = BitIsSet(opcode, 10);
6742
add = BitIsSet(opcode, 9);
6743
wback = BitIsSet(opcode, 8);
6744
6745
// if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
6746
if (t == 15)
6747
return false; // PLD is not implemented yet
6748
6749
// if Rn == '1111' then SEE LDRB (literal);
6750
if (n == 15)
6751
return EmulateLDRBLiteral(opcode, eEncodingT1);
6752
6753
// if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6754
if (BadReg(t) || (wback && (n == t)))
6755
return false;
6756
6757
break;
6758
6759
default:
6760
return false;
6761
}
6762
6763
uint32_t Rn =
6764
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6765
if (!success)
6766
return false;
6767
6768
addr_t address;
6769
addr_t offset_addr;
6770
6771
// offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6772
if (add)
6773
offset_addr = Rn + imm32;
6774
else
6775
offset_addr = Rn - imm32;
6776
6777
// address = if index then offset_addr else R[n];
6778
if (index)
6779
address = offset_addr;
6780
else
6781
address = Rn;
6782
6783
// R[t] = ZeroExtend(MemU[address,1], 32);
6784
std::optional<RegisterInfo> base_reg =
6785
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
6786
std::optional<RegisterInfo> data_reg =
6787
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
6788
6789
EmulateInstruction::Context context;
6790
context.type = eContextRegisterLoad;
6791
context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);
6792
6793
uint64_t data = MemURead(context, address, 1, 0, &success);
6794
if (!success)
6795
return false;
6796
6797
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
6798
return false;
6799
6800
// if wback then R[n] = offset_addr;
6801
if (wback) {
6802
context.type = eContextAdjustBaseRegister;
6803
context.SetAddress(offset_addr);
6804
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6805
offset_addr))
6806
return false;
6807
}
6808
}
6809
return true;
6810
}
6811
6812
// LDRB (literal) calculates an address from the PC value and an immediate
6813
// offset, loads a byte from memory,
6814
// zero-extends it to form a 32-bit word and writes it to a register.
6815
bool EmulateInstructionARM::EmulateLDRBLiteral(const uint32_t opcode,
6816
const ARMEncoding encoding) {
6817
#if 0
6818
if ConditionPassed() then
6819
EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6820
base = Align(PC,4);
6821
address = if add then (base + imm32) else (base - imm32);
6822
R[t] = ZeroExtend(MemU[address,1], 32);
6823
#endif
6824
6825
bool success = false;
6826
6827
if (ConditionPassed(opcode)) {
6828
uint32_t t;
6829
uint32_t imm32;
6830
bool add;
6831
switch (encoding) {
6832
case eEncodingT1:
6833
// t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6834
t = Bits32(opcode, 15, 12);
6835
imm32 = Bits32(opcode, 11, 0);
6836
add = BitIsSet(opcode, 23);
6837
6838
// if Rt == '1111' then SEE PLD;
6839
if (t == 15)
6840
return false; // PLD is not implemented yet
6841
6842
// if t == 13 then UNPREDICTABLE;
6843
if (t == 13)
6844
return false;
6845
6846
break;
6847
6848
case eEncodingA1:
6849
// t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6850
t = Bits32(opcode, 15, 12);
6851
imm32 = Bits32(opcode, 11, 0);
6852
add = BitIsSet(opcode, 23);
6853
6854
// if t == 15 then UNPREDICTABLE;
6855
if (t == 15)
6856
return false;
6857
break;
6858
6859
default:
6860
return false;
6861
}
6862
6863
// base = Align(PC,4);
6864
uint32_t pc_val = ReadCoreReg(PC_REG, &success);
6865
if (!success)
6866
return false;
6867
6868
uint32_t base = AlignPC(pc_val);
6869
6870
addr_t address;
6871
// address = if add then (base + imm32) else (base - imm32);
6872
if (add)
6873
address = base + imm32;
6874
else
6875
address = base - imm32;
6876
6877
// R[t] = ZeroExtend(MemU[address,1], 32);
6878
EmulateInstruction::Context context;
6879
context.type = eContextRelativeBranchImmediate;
6880
context.SetImmediate(address - base);
6881
6882
uint64_t data = MemURead(context, address, 1, 0, &success);
6883
if (!success)
6884
return false;
6885
6886
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
6887
return false;
6888
}
6889
return true;
6890
}
6891
6892
// LDRB (register) calculates an address from a base register value and an
6893
// offset rigister value, loads a byte from memory, zero-extends it to form a
6894
// 32-bit word, and writes it to a register. The offset register value can
6895
// optionally be shifted.
6896
bool EmulateInstructionARM::EmulateLDRBRegister(const uint32_t opcode,
6897
const ARMEncoding encoding) {
6898
#if 0
6899
if ConditionPassed() then
6900
EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6901
offset = Shift(R[m], shift_t, shift_n, APSR.C);
6902
offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6903
address = if index then offset_addr else R[n];
6904
R[t] = ZeroExtend(MemU[address,1],32);
6905
if wback then R[n] = offset_addr;
6906
#endif
6907
6908
bool success = false;
6909
6910
if (ConditionPassed(opcode)) {
6911
uint32_t t;
6912
uint32_t n;
6913
uint32_t m;
6914
bool index;
6915
bool add;
6916
bool wback;
6917
ARM_ShifterType shift_t;
6918
uint32_t shift_n;
6919
6920
// EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6921
switch (encoding) {
6922
case eEncodingT1:
6923
// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6924
t = Bits32(opcode, 2, 0);
6925
n = Bits32(opcode, 5, 3);
6926
m = Bits32(opcode, 8, 6);
6927
6928
// index = TRUE; add = TRUE; wback = FALSE;
6929
index = true;
6930
add = true;
6931
wback = false;
6932
6933
// (shift_t, shift_n) = (SRType_LSL, 0);
6934
shift_t = SRType_LSL;
6935
shift_n = 0;
6936
break;
6937
6938
case eEncodingT2:
6939
// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6940
t = Bits32(opcode, 15, 12);
6941
n = Bits32(opcode, 19, 16);
6942
m = Bits32(opcode, 3, 0);
6943
6944
// index = TRUE; add = TRUE; wback = FALSE;
6945
index = true;
6946
add = true;
6947
wback = false;
6948
6949
// (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6950
shift_t = SRType_LSL;
6951
shift_n = Bits32(opcode, 5, 4);
6952
6953
// if Rt == '1111' then SEE PLD;
6954
if (t == 15)
6955
return false; // PLD is not implemented yet
6956
6957
// if Rn == '1111' then SEE LDRB (literal);
6958
if (n == 15)
6959
return EmulateLDRBLiteral(opcode, eEncodingT1);
6960
6961
// if t == 13 || BadReg(m) then UNPREDICTABLE;
6962
if ((t == 13) || BadReg(m))
6963
return false;
6964
break;
6965
6966
case eEncodingA1: {
6967
// if P == '0' && W == '1' then SEE LDRBT;
6968
// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6969
t = Bits32(opcode, 15, 12);
6970
n = Bits32(opcode, 19, 16);
6971
m = Bits32(opcode, 3, 0);
6972
6973
// index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6974
// (W == '1');
6975
index = BitIsSet(opcode, 24);
6976
add = BitIsSet(opcode, 23);
6977
wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
6978
6979
// (shift_t, shift_n) = DecodeImmShift(type, imm5);
6980
uint32_t type = Bits32(opcode, 6, 5);
6981
uint32_t imm5 = Bits32(opcode, 11, 7);
6982
shift_n = DecodeImmShift(type, imm5, shift_t);
6983
6984
// if t == 15 || m == 15 then UNPREDICTABLE;
6985
if ((t == 15) || (m == 15))
6986
return false;
6987
6988
// if wback && (n == 15 || n == t) then UNPREDICTABLE;
6989
if (wback && ((n == 15) || (n == t)))
6990
return false;
6991
} break;
6992
6993
default:
6994
return false;
6995
}
6996
6997
addr_t offset_addr;
6998
addr_t address;
6999
7000
// offset = Shift(R[m], shift_t, shift_n, APSR.C);
7001
uint32_t Rm =
7002
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7003
if (!success)
7004
return false;
7005
7006
addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
7007
if (!success)
7008
return false;
7009
7010
// offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7011
uint32_t Rn =
7012
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7013
if (!success)
7014
return false;
7015
7016
if (add)
7017
offset_addr = Rn + offset;
7018
else
7019
offset_addr = Rn - offset;
7020
7021
// address = if index then offset_addr else R[n];
7022
if (index)
7023
address = offset_addr;
7024
else
7025
address = Rn;
7026
7027
// R[t] = ZeroExtend(MemU[address,1],32);
7028
std::optional<RegisterInfo> base_reg =
7029
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
7030
7031
EmulateInstruction::Context context;
7032
context.type = eContextRegisterLoad;
7033
context.SetRegisterPlusOffset(*base_reg, address - Rn);
7034
7035
uint64_t data = MemURead(context, address, 1, 0, &success);
7036
if (!success)
7037
return false;
7038
7039
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
7040
return false;
7041
7042
// if wback then R[n] = offset_addr;
7043
if (wback) {
7044
context.type = eContextAdjustBaseRegister;
7045
context.SetAddress(offset_addr);
7046
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7047
offset_addr))
7048
return false;
7049
}
7050
}
7051
return true;
7052
}
7053
7054
// LDRH (immediate, Thumb) calculates an address from a base register value and
7055
// an immediate offset, loads a
7056
// halfword from memory, zero-extends it to form a 32-bit word, and writes it
7057
// to a register. It can use offset, post-indexed, or pre-indexed addressing.
7058
bool EmulateInstructionARM::EmulateLDRHImmediate(const uint32_t opcode,
7059
const ARMEncoding encoding) {
7060
#if 0
7061
if ConditionPassed() then
7062
EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7063
offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7064
address = if index then offset_addr else R[n];
7065
data = MemU[address,2];
7066
if wback then R[n] = offset_addr;
7067
if UnalignedSupport() || address<0> = '0' then
7068
R[t] = ZeroExtend(data, 32);
7069
else // Can only apply before ARMv7
7070
R[t] = bits(32) UNKNOWN;
7071
#endif
7072
7073
bool success = false;
7074
7075
if (ConditionPassed(opcode)) {
7076
uint32_t t;
7077
uint32_t n;
7078
uint32_t imm32;
7079
bool index;
7080
bool add;
7081
bool wback;
7082
7083
// EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7084
switch (encoding) {
7085
case eEncodingT1:
7086
// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
7087
t = Bits32(opcode, 2, 0);
7088
n = Bits32(opcode, 5, 3);
7089
imm32 = Bits32(opcode, 10, 6) << 1;
7090
7091
// index = TRUE; add = TRUE; wback = FALSE;
7092
index = true;
7093
add = true;
7094
wback = false;
7095
7096
break;
7097
7098
case eEncodingT2:
7099
// if Rt == '1111' then SEE "Unallocated memory hints";
7100
// if Rn == '1111' then SEE LDRH (literal);
7101
// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7102
t = Bits32(opcode, 15, 12);
7103
n = Bits32(opcode, 19, 16);
7104
imm32 = Bits32(opcode, 11, 0);
7105
7106
// index = TRUE; add = TRUE; wback = FALSE;
7107
index = true;
7108
add = true;
7109
wback = false;
7110
7111
// if t == 13 then UNPREDICTABLE;
7112
if (t == 13)
7113
return false;
7114
break;
7115
7116
case eEncodingT3:
7117
// if Rn == '1111' then SEE LDRH (literal);
7118
// if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE
7119
// "Unallocated memory hints";
7120
// if P == '1' && U == '1' && W == '0' then SEE LDRHT;
7121
// if P == '0' && W == '0' then UNDEFINED;
7122
if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
7123
return false;
7124
7125
// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7126
t = Bits32(opcode, 15, 12);
7127
n = Bits32(opcode, 19, 16);
7128
imm32 = Bits32(opcode, 7, 0);
7129
7130
// index = (P == '1'); add = (U == '1'); wback = (W == '1');
7131
index = BitIsSet(opcode, 10);
7132
add = BitIsSet(opcode, 9);
7133
wback = BitIsSet(opcode, 8);
7134
7135
// if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7136
if (BadReg(t) || (wback && (n == t)))
7137
return false;
7138
break;
7139
7140
default:
7141
return false;
7142
}
7143
7144
// offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7145
uint32_t Rn =
7146
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7147
if (!success)
7148
return false;
7149
7150
addr_t offset_addr;
7151
addr_t address;
7152
7153
if (add)
7154
offset_addr = Rn + imm32;
7155
else
7156
offset_addr = Rn - imm32;
7157
7158
// address = if index then offset_addr else R[n];
7159
if (index)
7160
address = offset_addr;
7161
else
7162
address = Rn;
7163
7164
// data = MemU[address,2];
7165
std::optional<RegisterInfo> base_reg =
7166
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
7167
7168
EmulateInstruction::Context context;
7169
context.type = eContextRegisterLoad;
7170
context.SetRegisterPlusOffset(*base_reg, address - Rn);
7171
7172
uint64_t data = MemURead(context, address, 2, 0, &success);
7173
if (!success)
7174
return false;
7175
7176
// if wback then R[n] = offset_addr;
7177
if (wback) {
7178
context.type = eContextAdjustBaseRegister;
7179
context.SetAddress(offset_addr);
7180
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7181
offset_addr))
7182
return false;
7183
}
7184
7185
// if UnalignedSupport() || address<0> = '0' then
7186
if (UnalignedSupport() || BitIsClear(address, 0)) {
7187
// R[t] = ZeroExtend(data, 32);
7188
context.type = eContextRegisterLoad;
7189
context.SetRegisterPlusOffset(*base_reg, address - Rn);
7190
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7191
data))
7192
return false;
7193
} else // Can only apply before ARMv7
7194
{
7195
// R[t] = bits(32) UNKNOWN;
7196
WriteBits32Unknown(t);
7197
}
7198
}
7199
return true;
7200
}
7201
7202
// LDRH (literal) calculates an address from the PC value and an immediate
7203
// offset, loads a halfword from memory,
7204
// zero-extends it to form a 32-bit word, and writes it to a register.
7205
bool EmulateInstructionARM::EmulateLDRHLiteral(const uint32_t opcode,
7206
const ARMEncoding encoding) {
7207
#if 0
7208
if ConditionPassed() then
7209
EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7210
base = Align(PC,4);
7211
address = if add then (base + imm32) else (base - imm32);
7212
data = MemU[address,2];
7213
if UnalignedSupport() || address<0> = '0' then
7214
R[t] = ZeroExtend(data, 32);
7215
else // Can only apply before ARMv7
7216
R[t] = bits(32) UNKNOWN;
7217
#endif
7218
7219
bool success = false;
7220
7221
if (ConditionPassed(opcode)) {
7222
uint32_t t;
7223
uint32_t imm32;
7224
bool add;
7225
7226
// EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7227
switch (encoding) {
7228
case eEncodingT1:
7229
// if Rt == '1111' then SEE "Unallocated memory hints";
7230
// t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
7231
t = Bits32(opcode, 15, 12);
7232
imm32 = Bits32(opcode, 11, 0);
7233
add = BitIsSet(opcode, 23);
7234
7235
// if t == 13 then UNPREDICTABLE;
7236
if (t == 13)
7237
return false;
7238
7239
break;
7240
7241
case eEncodingA1: {
7242
uint32_t imm4H = Bits32(opcode, 11, 8);
7243
uint32_t imm4L = Bits32(opcode, 3, 0);
7244
7245
// t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7246
t = Bits32(opcode, 15, 12);
7247
imm32 = (imm4H << 4) | imm4L;
7248
add = BitIsSet(opcode, 23);
7249
7250
// if t == 15 then UNPREDICTABLE;
7251
if (t == 15)
7252
return false;
7253
break;
7254
}
7255
7256
default:
7257
return false;
7258
}
7259
7260
// base = Align(PC,4);
7261
uint64_t pc_value = ReadCoreReg(PC_REG, &success);
7262
if (!success)
7263
return false;
7264
7265
addr_t base = AlignPC(pc_value);
7266
addr_t address;
7267
7268
// address = if add then (base + imm32) else (base - imm32);
7269
if (add)
7270
address = base + imm32;
7271
else
7272
address = base - imm32;
7273
7274
// data = MemU[address,2];
7275
std::optional<RegisterInfo> base_reg =
7276
GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7277
7278
EmulateInstruction::Context context;
7279
context.type = eContextRegisterLoad;
7280
context.SetRegisterPlusOffset(*base_reg, address - base);
7281
7282
uint64_t data = MemURead(context, address, 2, 0, &success);
7283
if (!success)
7284
return false;
7285
7286
// if UnalignedSupport() || address<0> = '0' then
7287
if (UnalignedSupport() || BitIsClear(address, 0)) {
7288
// R[t] = ZeroExtend(data, 32);
7289
context.type = eContextRegisterLoad;
7290
context.SetRegisterPlusOffset(*base_reg, address - base);
7291
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7292
data))
7293
return false;
7294
7295
} else // Can only apply before ARMv7
7296
{
7297
// R[t] = bits(32) UNKNOWN;
7298
WriteBits32Unknown(t);
7299
}
7300
}
7301
return true;
7302
}
7303
7304
// LDRH (literal) calculates an address from a base register value and an offset
7305
// register value, loads a halfword
7306
// from memory, zero-extends it to form a 32-bit word, and writes it to a
7307
// register. The offset register value can be shifted left by 0, 1, 2, or 3
7308
// bits.
7309
bool EmulateInstructionARM::EmulateLDRHRegister(const uint32_t opcode,
7310
const ARMEncoding encoding) {
7311
#if 0
7312
if ConditionPassed() then
7313
EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7314
offset = Shift(R[m], shift_t, shift_n, APSR.C);
7315
offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7316
address = if index then offset_addr else R[n];
7317
data = MemU[address,2];
7318
if wback then R[n] = offset_addr;
7319
if UnalignedSupport() || address<0> = '0' then
7320
R[t] = ZeroExtend(data, 32);
7321
else // Can only apply before ARMv7
7322
R[t] = bits(32) UNKNOWN;
7323
#endif
7324
7325
bool success = false;
7326
7327
if (ConditionPassed(opcode)) {
7328
uint32_t t;
7329
uint32_t n;
7330
uint32_t m;
7331
bool index;
7332
bool add;
7333
bool wback;
7334
ARM_ShifterType shift_t;
7335
uint32_t shift_n;
7336
7337
// EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7338
switch (encoding) {
7339
case eEncodingT1:
7340
// if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
7341
// in ThumbEE";
7342
// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7343
t = Bits32(opcode, 2, 0);
7344
n = Bits32(opcode, 5, 3);
7345
m = Bits32(opcode, 8, 6);
7346
7347
// index = TRUE; add = TRUE; wback = FALSE;
7348
index = true;
7349
add = true;
7350
wback = false;
7351
7352
// (shift_t, shift_n) = (SRType_LSL, 0);
7353
shift_t = SRType_LSL;
7354
shift_n = 0;
7355
7356
break;
7357
7358
case eEncodingT2:
7359
// if Rn == '1111' then SEE LDRH (literal);
7360
// if Rt == '1111' then SEE "Unallocated memory hints";
7361
// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7362
t = Bits32(opcode, 15, 12);
7363
n = Bits32(opcode, 19, 16);
7364
m = Bits32(opcode, 3, 0);
7365
7366
// index = TRUE; add = TRUE; wback = FALSE;
7367
index = true;
7368
add = true;
7369
wback = false;
7370
7371
// (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7372
shift_t = SRType_LSL;
7373
shift_n = Bits32(opcode, 5, 4);
7374
7375
// if t == 13 || BadReg(m) then UNPREDICTABLE;
7376
if ((t == 13) || BadReg(m))
7377
return false;
7378
break;
7379
7380
case eEncodingA1:
7381
// if P == '0' && W == '1' then SEE LDRHT;
7382
// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7383
t = Bits32(opcode, 15, 12);
7384
n = Bits32(opcode, 19, 16);
7385
m = Bits32(opcode, 3, 0);
7386
7387
// index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7388
// (W == '1');
7389
index = BitIsSet(opcode, 24);
7390
add = BitIsSet(opcode, 23);
7391
wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
7392
7393
// (shift_t, shift_n) = (SRType_LSL, 0);
7394
shift_t = SRType_LSL;
7395
shift_n = 0;
7396
7397
// if t == 15 || m == 15 then UNPREDICTABLE;
7398
if ((t == 15) || (m == 15))
7399
return false;
7400
7401
// if wback && (n == 15 || n == t) then UNPREDICTABLE;
7402
if (wback && ((n == 15) || (n == t)))
7403
return false;
7404
7405
break;
7406
7407
default:
7408
return false;
7409
}
7410
7411
// offset = Shift(R[m], shift_t, shift_n, APSR.C);
7412
7413
uint64_t Rm =
7414
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7415
if (!success)
7416
return false;
7417
7418
addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
7419
if (!success)
7420
return false;
7421
7422
addr_t offset_addr;
7423
addr_t address;
7424
7425
// offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7426
uint64_t Rn =
7427
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7428
if (!success)
7429
return false;
7430
7431
if (add)
7432
offset_addr = Rn + offset;
7433
else
7434
offset_addr = Rn - offset;
7435
7436
// address = if index then offset_addr else R[n];
7437
if (index)
7438
address = offset_addr;
7439
else
7440
address = Rn;
7441
7442
// data = MemU[address,2];
7443
std::optional<RegisterInfo> base_reg =
7444
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
7445
std::optional<RegisterInfo> offset_reg =
7446
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
7447
7448
EmulateInstruction::Context context;
7449
context.type = eContextRegisterLoad;
7450
context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg);
7451
uint64_t data = MemURead(context, address, 2, 0, &success);
7452
if (!success)
7453
return false;
7454
7455
// if wback then R[n] = offset_addr;
7456
if (wback) {
7457
context.type = eContextAdjustBaseRegister;
7458
context.SetAddress(offset_addr);
7459
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7460
offset_addr))
7461
return false;
7462
}
7463
7464
// if UnalignedSupport() || address<0> = '0' then
7465
if (UnalignedSupport() || BitIsClear(address, 0)) {
7466
// R[t] = ZeroExtend(data, 32);
7467
context.type = eContextRegisterLoad;
7468
context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg);
7469
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7470
data))
7471
return false;
7472
} else // Can only apply before ARMv7
7473
{
7474
// R[t] = bits(32) UNKNOWN;
7475
WriteBits32Unknown(t);
7476
}
7477
}
7478
return true;
7479
}
7480
7481
// LDRSB (immediate) calculates an address from a base register value and an
7482
// immediate offset, loads a byte from
7483
// memory, sign-extends it to form a 32-bit word, and writes it to a register.
7484
// It can use offset, post-indexed, or pre-indexed addressing.
7485
bool EmulateInstructionARM::EmulateLDRSBImmediate(const uint32_t opcode,
7486
const ARMEncoding encoding) {
7487
#if 0
7488
if ConditionPassed() then
7489
EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7490
offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7491
address = if index then offset_addr else R[n];
7492
R[t] = SignExtend(MemU[address,1], 32);
7493
if wback then R[n] = offset_addr;
7494
#endif
7495
7496
bool success = false;
7497
7498
if (ConditionPassed(opcode)) {
7499
uint32_t t;
7500
uint32_t n;
7501
uint32_t imm32;
7502
bool index;
7503
bool add;
7504
bool wback;
7505
7506
// EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7507
switch (encoding) {
7508
case eEncodingT1:
7509
// if Rt == '1111' then SEE PLI;
7510
// if Rn == '1111' then SEE LDRSB (literal);
7511
// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7512
t = Bits32(opcode, 15, 12);
7513
n = Bits32(opcode, 19, 16);
7514
imm32 = Bits32(opcode, 11, 0);
7515
7516
// index = TRUE; add = TRUE; wback = FALSE;
7517
index = true;
7518
add = true;
7519
wback = false;
7520
7521
// if t == 13 then UNPREDICTABLE;
7522
if (t == 13)
7523
return false;
7524
7525
break;
7526
7527
case eEncodingT2:
7528
// if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
7529
// if Rn == '1111' then SEE LDRSB (literal);
7530
// if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
7531
// if P == '0' && W == '0' then UNDEFINED;
7532
if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
7533
return false;
7534
7535
// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7536
t = Bits32(opcode, 15, 12);
7537
n = Bits32(opcode, 19, 16);
7538
imm32 = Bits32(opcode, 7, 0);
7539
7540
// index = (P == '1'); add = (U == '1'); wback = (W == '1');
7541
index = BitIsSet(opcode, 10);
7542
add = BitIsSet(opcode, 9);
7543
wback = BitIsSet(opcode, 8);
7544
7545
// if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7546
if (((t == 13) ||
7547
((t == 15) && (BitIsClear(opcode, 10) || BitIsSet(opcode, 9) ||
7548
BitIsSet(opcode, 8)))) ||
7549
(wback && (n == t)))
7550
return false;
7551
7552
break;
7553
7554
case eEncodingA1: {
7555
// if Rn == '1111' then SEE LDRSB (literal);
7556
// if P == '0' && W == '1' then SEE LDRSBT;
7557
// t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7558
t = Bits32(opcode, 15, 12);
7559
n = Bits32(opcode, 19, 16);
7560
7561
uint32_t imm4H = Bits32(opcode, 11, 8);
7562
uint32_t imm4L = Bits32(opcode, 3, 0);
7563
imm32 = (imm4H << 4) | imm4L;
7564
7565
// index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7566
// (W == '1');
7567
index = BitIsSet(opcode, 24);
7568
add = BitIsSet(opcode, 23);
7569
wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
7570
7571
// if t == 15 || (wback && n == t) then UNPREDICTABLE;
7572
if ((t == 15) || (wback && (n == t)))
7573
return false;
7574
7575
break;
7576
}
7577
7578
default:
7579
return false;
7580
}
7581
7582
uint64_t Rn = ReadCoreReg(n, &success);
7583
if (!success)
7584
return false;
7585
7586
addr_t offset_addr;
7587
addr_t address;
7588
7589
// offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7590
if (add)
7591
offset_addr = Rn + imm32;
7592
else
7593
offset_addr = Rn - imm32;
7594
7595
// address = if index then offset_addr else R[n];
7596
if (index)
7597
address = offset_addr;
7598
else
7599
address = Rn;
7600
7601
// R[t] = SignExtend(MemU[address,1], 32);
7602
std::optional<RegisterInfo> base_reg =
7603
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
7604
7605
EmulateInstruction::Context context;
7606
context.type = eContextRegisterLoad;
7607
context.SetRegisterPlusOffset(*base_reg, address - Rn);
7608
7609
uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);
7610
if (!success)
7611
return false;
7612
7613
int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7614
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7615
(uint64_t)signed_data))
7616
return false;
7617
7618
// if wback then R[n] = offset_addr;
7619
if (wback) {
7620
context.type = eContextAdjustBaseRegister;
7621
context.SetAddress(offset_addr);
7622
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7623
offset_addr))
7624
return false;
7625
}
7626
}
7627
7628
return true;
7629
}
7630
7631
// LDRSB (literal) calculates an address from the PC value and an immediate
7632
// offset, loads a byte from memory,
7633
// sign-extends it to form a 32-bit word, and writes tit to a register.
7634
bool EmulateInstructionARM::EmulateLDRSBLiteral(const uint32_t opcode,
7635
const ARMEncoding encoding) {
7636
#if 0
7637
if ConditionPassed() then
7638
EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7639
base = Align(PC,4);
7640
address = if add then (base + imm32) else (base - imm32);
7641
R[t] = SignExtend(MemU[address,1], 32);
7642
#endif
7643
7644
bool success = false;
7645
7646
if (ConditionPassed(opcode)) {
7647
uint32_t t;
7648
uint32_t imm32;
7649
bool add;
7650
7651
// EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7652
switch (encoding) {
7653
case eEncodingT1:
7654
// if Rt == '1111' then SEE PLI;
7655
// t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
7656
t = Bits32(opcode, 15, 12);
7657
imm32 = Bits32(opcode, 11, 0);
7658
add = BitIsSet(opcode, 23);
7659
7660
// if t == 13 then UNPREDICTABLE;
7661
if (t == 13)
7662
return false;
7663
7664
break;
7665
7666
case eEncodingA1: {
7667
// t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7668
t = Bits32(opcode, 15, 12);
7669
uint32_t imm4H = Bits32(opcode, 11, 8);
7670
uint32_t imm4L = Bits32(opcode, 3, 0);
7671
imm32 = (imm4H << 4) | imm4L;
7672
add = BitIsSet(opcode, 23);
7673
7674
// if t == 15 then UNPREDICTABLE;
7675
if (t == 15)
7676
return false;
7677
7678
break;
7679
}
7680
7681
default:
7682
return false;
7683
}
7684
7685
// base = Align(PC,4);
7686
uint64_t pc_value = ReadCoreReg(PC_REG, &success);
7687
if (!success)
7688
return false;
7689
uint64_t base = AlignPC(pc_value);
7690
7691
// address = if add then (base + imm32) else (base - imm32);
7692
addr_t address;
7693
if (add)
7694
address = base + imm32;
7695
else
7696
address = base - imm32;
7697
7698
// R[t] = SignExtend(MemU[address,1], 32);
7699
std::optional<RegisterInfo> base_reg =
7700
GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7701
7702
EmulateInstruction::Context context;
7703
context.type = eContextRegisterLoad;
7704
context.SetRegisterPlusOffset(*base_reg, address - base);
7705
7706
uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);
7707
if (!success)
7708
return false;
7709
7710
int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7711
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7712
(uint64_t)signed_data))
7713
return false;
7714
}
7715
return true;
7716
}
7717
7718
// LDRSB (register) calculates an address from a base register value and an
7719
// offset register value, loadsa byte from
7720
// memory, sign-extends it to form a 32-bit word, and writes it to a register.
7721
// The offset register value can be shifted left by 0, 1, 2, or 3 bits.
7722
bool EmulateInstructionARM::EmulateLDRSBRegister(const uint32_t opcode,
7723
const ARMEncoding encoding) {
7724
#if 0
7725
if ConditionPassed() then
7726
EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7727
offset = Shift(R[m], shift_t, shift_n, APSR.C);
7728
offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7729
address = if index then offset_addr else R[n];
7730
R[t] = SignExtend(MemU[address,1], 32);
7731
if wback then R[n] = offset_addr;
7732
#endif
7733
7734
bool success = false;
7735
7736
if (ConditionPassed(opcode)) {
7737
uint32_t t;
7738
uint32_t n;
7739
uint32_t m;
7740
bool index;
7741
bool add;
7742
bool wback;
7743
ARM_ShifterType shift_t;
7744
uint32_t shift_n;
7745
7746
// EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7747
switch (encoding) {
7748
case eEncodingT1:
7749
// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7750
t = Bits32(opcode, 2, 0);
7751
n = Bits32(opcode, 5, 3);
7752
m = Bits32(opcode, 8, 6);
7753
7754
// index = TRUE; add = TRUE; wback = FALSE;
7755
index = true;
7756
add = true;
7757
wback = false;
7758
7759
// (shift_t, shift_n) = (SRType_LSL, 0);
7760
shift_t = SRType_LSL;
7761
shift_n = 0;
7762
7763
break;
7764
7765
case eEncodingT2:
7766
// if Rt == '1111' then SEE PLI;
7767
// if Rn == '1111' then SEE LDRSB (literal);
7768
// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7769
t = Bits32(opcode, 15, 12);
7770
n = Bits32(opcode, 19, 16);
7771
m = Bits32(opcode, 3, 0);
7772
7773
// index = TRUE; add = TRUE; wback = FALSE;
7774
index = true;
7775
add = true;
7776
wback = false;
7777
7778
// (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7779
shift_t = SRType_LSL;
7780
shift_n = Bits32(opcode, 5, 4);
7781
7782
// if t == 13 || BadReg(m) then UNPREDICTABLE;
7783
if ((t == 13) || BadReg(m))
7784
return false;
7785
break;
7786
7787
case eEncodingA1:
7788
// if P == '0' && W == '1' then SEE LDRSBT;
7789
// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7790
t = Bits32(opcode, 15, 12);
7791
n = Bits32(opcode, 19, 16);
7792
m = Bits32(opcode, 3, 0);
7793
7794
// index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7795
// (W == '1');
7796
index = BitIsSet(opcode, 24);
7797
add = BitIsSet(opcode, 23);
7798
wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
7799
7800
// (shift_t, shift_n) = (SRType_LSL, 0);
7801
shift_t = SRType_LSL;
7802
shift_n = 0;
7803
7804
// if t == 15 || m == 15 then UNPREDICTABLE;
7805
if ((t == 15) || (m == 15))
7806
return false;
7807
7808
// if wback && (n == 15 || n == t) then UNPREDICTABLE;
7809
if (wback && ((n == 15) || (n == t)))
7810
return false;
7811
break;
7812
7813
default:
7814
return false;
7815
}
7816
7817
uint64_t Rm =
7818
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7819
if (!success)
7820
return false;
7821
7822
// offset = Shift(R[m], shift_t, shift_n, APSR.C);
7823
addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
7824
if (!success)
7825
return false;
7826
7827
addr_t offset_addr;
7828
addr_t address;
7829
7830
// offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7831
uint64_t Rn =
7832
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7833
if (!success)
7834
return false;
7835
7836
if (add)
7837
offset_addr = Rn + offset;
7838
else
7839
offset_addr = Rn - offset;
7840
7841
// address = if index then offset_addr else R[n];
7842
if (index)
7843
address = offset_addr;
7844
else
7845
address = Rn;
7846
7847
// R[t] = SignExtend(MemU[address,1], 32);
7848
std::optional<RegisterInfo> base_reg =
7849
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
7850
std::optional<RegisterInfo> offset_reg =
7851
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
7852
7853
EmulateInstruction::Context context;
7854
context.type = eContextRegisterLoad;
7855
context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg);
7856
7857
uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);
7858
if (!success)
7859
return false;
7860
7861
int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7862
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7863
(uint64_t)signed_data))
7864
return false;
7865
7866
// if wback then R[n] = offset_addr;
7867
if (wback) {
7868
context.type = eContextAdjustBaseRegister;
7869
context.SetAddress(offset_addr);
7870
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7871
offset_addr))
7872
return false;
7873
}
7874
}
7875
return true;
7876
}
7877
7878
// LDRSH (immediate) calculates an address from a base register value and an
7879
// immediate offset, loads a halfword from
7880
// memory, sign-extends it to form a 32-bit word, and writes it to a register.
7881
// It can use offset, post-indexed, or pre-indexed addressing.
7882
bool EmulateInstructionARM::EmulateLDRSHImmediate(const uint32_t opcode,
7883
const ARMEncoding encoding) {
7884
#if 0
7885
if ConditionPassed() then
7886
EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7887
offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7888
address = if index then offset_addr else R[n];
7889
data = MemU[address,2];
7890
if wback then R[n] = offset_addr;
7891
if UnalignedSupport() || address<0> = '0' then
7892
R[t] = SignExtend(data, 32);
7893
else // Can only apply before ARMv7
7894
R[t] = bits(32) UNKNOWN;
7895
#endif
7896
7897
bool success = false;
7898
7899
if (ConditionPassed(opcode)) {
7900
uint32_t t;
7901
uint32_t n;
7902
uint32_t imm32;
7903
bool index;
7904
bool add;
7905
bool wback;
7906
7907
// EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7908
switch (encoding) {
7909
case eEncodingT1:
7910
// if Rn == '1111' then SEE LDRSH (literal);
7911
// if Rt == '1111' then SEE "Unallocated memory hints";
7912
// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7913
t = Bits32(opcode, 15, 12);
7914
n = Bits32(opcode, 19, 16);
7915
imm32 = Bits32(opcode, 11, 0);
7916
7917
// index = TRUE; add = TRUE; wback = FALSE;
7918
index = true;
7919
add = true;
7920
wback = false;
7921
7922
// if t == 13 then UNPREDICTABLE;
7923
if (t == 13)
7924
return false;
7925
7926
break;
7927
7928
case eEncodingT2:
7929
// if Rn == '1111' then SEE LDRSH (literal);
7930
// if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE
7931
// "Unallocated memory hints";
7932
// if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7933
// if P == '0' && W == '0' then UNDEFINED;
7934
if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))
7935
return false;
7936
7937
// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7938
t = Bits32(opcode, 15, 12);
7939
n = Bits32(opcode, 19, 16);
7940
imm32 = Bits32(opcode, 7, 0);
7941
7942
// index = (P == '1'); add = (U == '1'); wback = (W == '1');
7943
index = BitIsSet(opcode, 10);
7944
add = BitIsSet(opcode, 9);
7945
wback = BitIsSet(opcode, 8);
7946
7947
// if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7948
if (BadReg(t) || (wback && (n == t)))
7949
return false;
7950
7951
break;
7952
7953
case eEncodingA1: {
7954
// if Rn == '1111' then SEE LDRSH (literal);
7955
// if P == '0' && W == '1' then SEE LDRSHT;
7956
// t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7957
t = Bits32(opcode, 15, 12);
7958
n = Bits32(opcode, 19, 16);
7959
uint32_t imm4H = Bits32(opcode, 11, 8);
7960
uint32_t imm4L = Bits32(opcode, 3, 0);
7961
imm32 = (imm4H << 4) | imm4L;
7962
7963
// index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7964
// (W == '1');
7965
index = BitIsSet(opcode, 24);
7966
add = BitIsSet(opcode, 23);
7967
wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
7968
7969
// if t == 15 || (wback && n == t) then UNPREDICTABLE;
7970
if ((t == 15) || (wback && (n == t)))
7971
return false;
7972
7973
break;
7974
}
7975
7976
default:
7977
return false;
7978
}
7979
7980
// offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7981
uint64_t Rn =
7982
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7983
if (!success)
7984
return false;
7985
7986
addr_t offset_addr;
7987
if (add)
7988
offset_addr = Rn + imm32;
7989
else
7990
offset_addr = Rn - imm32;
7991
7992
// address = if index then offset_addr else R[n];
7993
addr_t address;
7994
if (index)
7995
address = offset_addr;
7996
else
7997
address = Rn;
7998
7999
// data = MemU[address,2];
8000
std::optional<RegisterInfo> base_reg =
8001
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
8002
8003
EmulateInstruction::Context context;
8004
context.type = eContextRegisterLoad;
8005
context.SetRegisterPlusOffset(*base_reg, address - Rn);
8006
8007
uint64_t data = MemURead(context, address, 2, 0, &success);
8008
if (!success)
8009
return false;
8010
8011
// if wback then R[n] = offset_addr;
8012
if (wback) {
8013
context.type = eContextAdjustBaseRegister;
8014
context.SetAddress(offset_addr);
8015
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8016
offset_addr))
8017
return false;
8018
}
8019
8020
// if UnalignedSupport() || address<0> = '0' then
8021
if (UnalignedSupport() || BitIsClear(address, 0)) {
8022
// R[t] = SignExtend(data, 32);
8023
int64_t signed_data = llvm::SignExtend64<16>(data);
8024
context.type = eContextRegisterLoad;
8025
context.SetRegisterPlusOffset(*base_reg, address - Rn);
8026
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
8027
(uint64_t)signed_data))
8028
return false;
8029
} else // Can only apply before ARMv7
8030
{
8031
// R[t] = bits(32) UNKNOWN;
8032
WriteBits32Unknown(t);
8033
}
8034
}
8035
return true;
8036
}
8037
8038
// LDRSH (literal) calculates an address from the PC value and an immediate
8039
// offset, loads a halfword from memory,
8040
// sign-extends it to from a 32-bit word, and writes it to a register.
8041
bool EmulateInstructionARM::EmulateLDRSHLiteral(const uint32_t opcode,
8042
const ARMEncoding encoding) {
8043
#if 0
8044
if ConditionPassed() then
8045
EncodingSpecificOperations(); NullCheckIfThumbEE(15);
8046
base = Align(PC,4);
8047
address = if add then (base + imm32) else (base - imm32);
8048
data = MemU[address,2];
8049
if UnalignedSupport() || address<0> = '0' then
8050
R[t] = SignExtend(data, 32);
8051
else // Can only apply before ARMv7
8052
R[t] = bits(32) UNKNOWN;
8053
#endif
8054
8055
bool success = false;
8056
8057
if (ConditionPassed(opcode)) {
8058
uint32_t t;
8059
uint32_t imm32;
8060
bool add;
8061
8062
// EncodingSpecificOperations(); NullCheckIfThumbEE(15);
8063
switch (encoding) {
8064
case eEncodingT1:
8065
// if Rt == '1111' then SEE "Unallocated memory hints";
8066
// t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
8067
t = Bits32(opcode, 15, 12);
8068
imm32 = Bits32(opcode, 11, 0);
8069
add = BitIsSet(opcode, 23);
8070
8071
// if t == 13 then UNPREDICTABLE;
8072
if (t == 13)
8073
return false;
8074
8075
break;
8076
8077
case eEncodingA1: {
8078
// t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
8079
t = Bits32(opcode, 15, 12);
8080
uint32_t imm4H = Bits32(opcode, 11, 8);
8081
uint32_t imm4L = Bits32(opcode, 3, 0);
8082
imm32 = (imm4H << 4) | imm4L;
8083
add = BitIsSet(opcode, 23);
8084
8085
// if t == 15 then UNPREDICTABLE;
8086
if (t == 15)
8087
return false;
8088
8089
break;
8090
}
8091
default:
8092
return false;
8093
}
8094
8095
// base = Align(PC,4);
8096
uint64_t pc_value = ReadCoreReg(PC_REG, &success);
8097
if (!success)
8098
return false;
8099
8100
uint64_t base = AlignPC(pc_value);
8101
8102
addr_t address;
8103
// address = if add then (base + imm32) else (base - imm32);
8104
if (add)
8105
address = base + imm32;
8106
else
8107
address = base - imm32;
8108
8109
// data = MemU[address,2];
8110
std::optional<RegisterInfo> base_reg =
8111
GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
8112
8113
EmulateInstruction::Context context;
8114
context.type = eContextRegisterLoad;
8115
context.SetRegisterPlusOffset(*base_reg, imm32);
8116
8117
uint64_t data = MemURead(context, address, 2, 0, &success);
8118
if (!success)
8119
return false;
8120
8121
// if UnalignedSupport() || address<0> = '0' then
8122
if (UnalignedSupport() || BitIsClear(address, 0)) {
8123
// R[t] = SignExtend(data, 32);
8124
int64_t signed_data = llvm::SignExtend64<16>(data);
8125
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
8126
(uint64_t)signed_data))
8127
return false;
8128
} else // Can only apply before ARMv7
8129
{
8130
// R[t] = bits(32) UNKNOWN;
8131
WriteBits32Unknown(t);
8132
}
8133
}
8134
return true;
8135
}
8136
8137
// LDRSH (register) calculates an address from a base register value and an
8138
// offset register value, loads a halfword
8139
// from memory, sign-extends it to form a 32-bit word, and writes it to a
8140
// register. The offset register value can be shifted left by 0, 1, 2, or 3
8141
// bits.
8142
bool EmulateInstructionARM::EmulateLDRSHRegister(const uint32_t opcode,
8143
const ARMEncoding encoding) {
8144
#if 0
8145
if ConditionPassed() then
8146
EncodingSpecificOperations(); NullCheckIfThumbEE(n);
8147
offset = Shift(R[m], shift_t, shift_n, APSR.C);
8148
offset_addr = if add then (R[n] + offset) else (R[n] - offset);
8149
address = if index then offset_addr else R[n];
8150
data = MemU[address,2];
8151
if wback then R[n] = offset_addr;
8152
if UnalignedSupport() || address<0> = '0' then
8153
R[t] = SignExtend(data, 32);
8154
else // Can only apply before ARMv7
8155
R[t] = bits(32) UNKNOWN;
8156
#endif
8157
8158
bool success = false;
8159
8160
if (ConditionPassed(opcode)) {
8161
uint32_t t;
8162
uint32_t n;
8163
uint32_t m;
8164
bool index;
8165
bool add;
8166
bool wback;
8167
ARM_ShifterType shift_t;
8168
uint32_t shift_n;
8169
8170
// EncodingSpecificOperations(); NullCheckIfThumbEE(n);
8171
switch (encoding) {
8172
case eEncodingT1:
8173
// if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
8174
// in ThumbEE";
8175
// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8176
t = Bits32(opcode, 2, 0);
8177
n = Bits32(opcode, 5, 3);
8178
m = Bits32(opcode, 8, 6);
8179
8180
// index = TRUE; add = TRUE; wback = FALSE;
8181
index = true;
8182
add = true;
8183
wback = false;
8184
8185
// (shift_t, shift_n) = (SRType_LSL, 0);
8186
shift_t = SRType_LSL;
8187
shift_n = 0;
8188
8189
break;
8190
8191
case eEncodingT2:
8192
// if Rn == '1111' then SEE LDRSH (literal);
8193
// if Rt == '1111' then SEE "Unallocated memory hints";
8194
// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8195
t = Bits32(opcode, 15, 12);
8196
n = Bits32(opcode, 19, 16);
8197
m = Bits32(opcode, 3, 0);
8198
8199
// index = TRUE; add = TRUE; wback = FALSE;
8200
index = true;
8201
add = true;
8202
wback = false;
8203
8204
// (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
8205
shift_t = SRType_LSL;
8206
shift_n = Bits32(opcode, 5, 4);
8207
8208
// if t == 13 || BadReg(m) then UNPREDICTABLE;
8209
if ((t == 13) || BadReg(m))
8210
return false;
8211
8212
break;
8213
8214
case eEncodingA1:
8215
// if P == '0' && W == '1' then SEE LDRSHT;
8216
// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8217
t = Bits32(opcode, 15, 12);
8218
n = Bits32(opcode, 19, 16);
8219
m = Bits32(opcode, 3, 0);
8220
8221
// index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
8222
// (W == '1');
8223
index = BitIsSet(opcode, 24);
8224
add = BitIsSet(opcode, 23);
8225
wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
8226
8227
// (shift_t, shift_n) = (SRType_LSL, 0);
8228
shift_t = SRType_LSL;
8229
shift_n = 0;
8230
8231
// if t == 15 || m == 15 then UNPREDICTABLE;
8232
if ((t == 15) || (m == 15))
8233
return false;
8234
8235
// if wback && (n == 15 || n == t) then UNPREDICTABLE;
8236
if (wback && ((n == 15) || (n == t)))
8237
return false;
8238
8239
break;
8240
8241
default:
8242
return false;
8243
}
8244
8245
uint64_t Rm =
8246
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8247
if (!success)
8248
return false;
8249
8250
uint64_t Rn =
8251
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8252
if (!success)
8253
return false;
8254
8255
// offset = Shift(R[m], shift_t, shift_n, APSR.C);
8256
addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
8257
if (!success)
8258
return false;
8259
8260
addr_t offset_addr;
8261
addr_t address;
8262
8263
// offset_addr = if add then (R[n] + offset) else (R[n] - offset);
8264
if (add)
8265
offset_addr = Rn + offset;
8266
else
8267
offset_addr = Rn - offset;
8268
8269
// address = if index then offset_addr else R[n];
8270
if (index)
8271
address = offset_addr;
8272
else
8273
address = Rn;
8274
8275
// data = MemU[address,2];
8276
std::optional<RegisterInfo> base_reg =
8277
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
8278
std::optional<RegisterInfo> offset_reg =
8279
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
8280
8281
EmulateInstruction::Context context;
8282
context.type = eContextRegisterLoad;
8283
context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg);
8284
8285
uint64_t data = MemURead(context, address, 2, 0, &success);
8286
if (!success)
8287
return false;
8288
8289
// if wback then R[n] = offset_addr;
8290
if (wback) {
8291
context.type = eContextAdjustBaseRegister;
8292
context.SetAddress(offset_addr);
8293
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8294
offset_addr))
8295
return false;
8296
}
8297
8298
// if UnalignedSupport() || address<0> = '0' then
8299
if (UnalignedSupport() || BitIsClear(address, 0)) {
8300
// R[t] = SignExtend(data, 32);
8301
context.type = eContextRegisterLoad;
8302
context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg);
8303
8304
int64_t signed_data = llvm::SignExtend64<16>(data);
8305
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
8306
(uint64_t)signed_data))
8307
return false;
8308
} else // Can only apply before ARMv7
8309
{
8310
// R[t] = bits(32) UNKNOWN;
8311
WriteBits32Unknown(t);
8312
}
8313
}
8314
return true;
8315
}
8316
8317
// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and
8318
// writes the result to the destination
8319
// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before
8320
// extracting the 8-bit value.
8321
bool EmulateInstructionARM::EmulateSXTB(const uint32_t opcode,
8322
const ARMEncoding encoding) {
8323
#if 0
8324
if ConditionPassed() then
8325
EncodingSpecificOperations();
8326
rotated = ROR(R[m], rotation);
8327
R[d] = SignExtend(rotated<7:0>, 32);
8328
#endif
8329
8330
bool success = false;
8331
8332
if (ConditionPassed(opcode)) {
8333
uint32_t d;
8334
uint32_t m;
8335
uint32_t rotation;
8336
8337
// EncodingSpecificOperations();
8338
switch (encoding) {
8339
case eEncodingT1:
8340
// d = UInt(Rd); m = UInt(Rm); rotation = 0;
8341
d = Bits32(opcode, 2, 0);
8342
m = Bits32(opcode, 5, 3);
8343
rotation = 0;
8344
8345
break;
8346
8347
case eEncodingT2:
8348
// d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8349
d = Bits32(opcode, 11, 8);
8350
m = Bits32(opcode, 3, 0);
8351
rotation = Bits32(opcode, 5, 4) << 3;
8352
8353
// if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8354
if (BadReg(d) || BadReg(m))
8355
return false;
8356
8357
break;
8358
8359
case eEncodingA1:
8360
// d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8361
d = Bits32(opcode, 15, 12);
8362
m = Bits32(opcode, 3, 0);
8363
rotation = Bits32(opcode, 11, 10) << 3;
8364
8365
// if d == 15 || m == 15 then UNPREDICTABLE;
8366
if ((d == 15) || (m == 15))
8367
return false;
8368
8369
break;
8370
8371
default:
8372
return false;
8373
}
8374
8375
uint64_t Rm =
8376
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8377
if (!success)
8378
return false;
8379
8380
// rotated = ROR(R[m], rotation);
8381
uint64_t rotated = ROR(Rm, rotation, &success);
8382
if (!success)
8383
return false;
8384
8385
// R[d] = SignExtend(rotated<7:0>, 32);
8386
int64_t data = llvm::SignExtend64<8>(rotated);
8387
8388
std::optional<RegisterInfo> source_reg =
8389
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
8390
8391
EmulateInstruction::Context context;
8392
context.type = eContextRegisterLoad;
8393
context.SetRegister(*source_reg);
8394
8395
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8396
(uint64_t)data))
8397
return false;
8398
}
8399
return true;
8400
}
8401
8402
// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and
8403
// writes the result to the destination
8404
// register. You can specify a rotation by 0, 8, 16, or 24 bits before
8405
// extracting the 16-bit value.
8406
bool EmulateInstructionARM::EmulateSXTH(const uint32_t opcode,
8407
const ARMEncoding encoding) {
8408
#if 0
8409
if ConditionPassed() then
8410
EncodingSpecificOperations();
8411
rotated = ROR(R[m], rotation);
8412
R[d] = SignExtend(rotated<15:0>, 32);
8413
#endif
8414
8415
bool success = false;
8416
8417
if (ConditionPassed(opcode)) {
8418
uint32_t d;
8419
uint32_t m;
8420
uint32_t rotation;
8421
8422
// EncodingSpecificOperations();
8423
switch (encoding) {
8424
case eEncodingT1:
8425
// d = UInt(Rd); m = UInt(Rm); rotation = 0;
8426
d = Bits32(opcode, 2, 0);
8427
m = Bits32(opcode, 5, 3);
8428
rotation = 0;
8429
8430
break;
8431
8432
case eEncodingT2:
8433
// d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8434
d = Bits32(opcode, 11, 8);
8435
m = Bits32(opcode, 3, 0);
8436
rotation = Bits32(opcode, 5, 4) << 3;
8437
8438
// if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8439
if (BadReg(d) || BadReg(m))
8440
return false;
8441
8442
break;
8443
8444
case eEncodingA1:
8445
// d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8446
d = Bits32(opcode, 15, 12);
8447
m = Bits32(opcode, 3, 0);
8448
rotation = Bits32(opcode, 11, 10) << 3;
8449
8450
// if d == 15 || m == 15 then UNPREDICTABLE;
8451
if ((d == 15) || (m == 15))
8452
return false;
8453
8454
break;
8455
8456
default:
8457
return false;
8458
}
8459
8460
uint64_t Rm =
8461
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8462
if (!success)
8463
return false;
8464
8465
// rotated = ROR(R[m], rotation);
8466
uint64_t rotated = ROR(Rm, rotation, &success);
8467
if (!success)
8468
return false;
8469
8470
// R[d] = SignExtend(rotated<15:0>, 32);
8471
std::optional<RegisterInfo> source_reg =
8472
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
8473
8474
EmulateInstruction::Context context;
8475
context.type = eContextRegisterLoad;
8476
context.SetRegister(*source_reg);
8477
8478
int64_t data = llvm::SignExtend64<16>(rotated);
8479
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8480
(uint64_t)data))
8481
return false;
8482
}
8483
8484
return true;
8485
}
8486
8487
// UXTB extracts an 8-bit value from a register, zero-extends it to 32 bits, and
8488
// writes the result to the destination
8489
// register. You can specify a rotation by 0, 8, 16, or 24 bits before
8490
// extracting the 8-bit value.
8491
bool EmulateInstructionARM::EmulateUXTB(const uint32_t opcode,
8492
const ARMEncoding encoding) {
8493
#if 0
8494
if ConditionPassed() then
8495
EncodingSpecificOperations();
8496
rotated = ROR(R[m], rotation);
8497
R[d] = ZeroExtend(rotated<7:0>, 32);
8498
#endif
8499
8500
bool success = false;
8501
8502
if (ConditionPassed(opcode)) {
8503
uint32_t d;
8504
uint32_t m;
8505
uint32_t rotation;
8506
8507
// EncodingSpecificOperations();
8508
switch (encoding) {
8509
case eEncodingT1:
8510
// d = UInt(Rd); m = UInt(Rm); rotation = 0;
8511
d = Bits32(opcode, 2, 0);
8512
m = Bits32(opcode, 5, 3);
8513
rotation = 0;
8514
8515
break;
8516
8517
case eEncodingT2:
8518
// d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8519
d = Bits32(opcode, 11, 8);
8520
m = Bits32(opcode, 3, 0);
8521
rotation = Bits32(opcode, 5, 4) << 3;
8522
8523
// if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8524
if (BadReg(d) || BadReg(m))
8525
return false;
8526
8527
break;
8528
8529
case eEncodingA1:
8530
// d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8531
d = Bits32(opcode, 15, 12);
8532
m = Bits32(opcode, 3, 0);
8533
rotation = Bits32(opcode, 11, 10) << 3;
8534
8535
// if d == 15 || m == 15 then UNPREDICTABLE;
8536
if ((d == 15) || (m == 15))
8537
return false;
8538
8539
break;
8540
8541
default:
8542
return false;
8543
}
8544
8545
uint64_t Rm =
8546
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8547
if (!success)
8548
return false;
8549
8550
// rotated = ROR(R[m], rotation);
8551
uint64_t rotated = ROR(Rm, rotation, &success);
8552
if (!success)
8553
return false;
8554
8555
// R[d] = ZeroExtend(rotated<7:0>, 32);
8556
std::optional<RegisterInfo> source_reg =
8557
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
8558
8559
EmulateInstruction::Context context;
8560
context.type = eContextRegisterLoad;
8561
context.SetRegister(*source_reg);
8562
8563
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8564
Bits32(rotated, 7, 0)))
8565
return false;
8566
}
8567
return true;
8568
}
8569
8570
// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and
8571
// writes the result to the destination
8572
// register. You can specify a rotation by 0, 8, 16, or 24 bits before
8573
// extracting the 16-bit value.
8574
bool EmulateInstructionARM::EmulateUXTH(const uint32_t opcode,
8575
const ARMEncoding encoding) {
8576
#if 0
8577
if ConditionPassed() then
8578
EncodingSpecificOperations();
8579
rotated = ROR(R[m], rotation);
8580
R[d] = ZeroExtend(rotated<15:0>, 32);
8581
#endif
8582
8583
bool success = false;
8584
8585
if (ConditionPassed(opcode)) {
8586
uint32_t d;
8587
uint32_t m;
8588
uint32_t rotation;
8589
8590
switch (encoding) {
8591
case eEncodingT1:
8592
// d = UInt(Rd); m = UInt(Rm); rotation = 0;
8593
d = Bits32(opcode, 2, 0);
8594
m = Bits32(opcode, 5, 3);
8595
rotation = 0;
8596
8597
break;
8598
8599
case eEncodingT2:
8600
// d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8601
d = Bits32(opcode, 11, 8);
8602
m = Bits32(opcode, 3, 0);
8603
rotation = Bits32(opcode, 5, 4) << 3;
8604
8605
// if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8606
if (BadReg(d) || BadReg(m))
8607
return false;
8608
8609
break;
8610
8611
case eEncodingA1:
8612
// d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8613
d = Bits32(opcode, 15, 12);
8614
m = Bits32(opcode, 3, 0);
8615
rotation = Bits32(opcode, 11, 10) << 3;
8616
8617
// if d == 15 || m == 15 then UNPREDICTABLE;
8618
if ((d == 15) || (m == 15))
8619
return false;
8620
8621
break;
8622
8623
default:
8624
return false;
8625
}
8626
8627
uint64_t Rm =
8628
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8629
if (!success)
8630
return false;
8631
8632
// rotated = ROR(R[m], rotation);
8633
uint64_t rotated = ROR(Rm, rotation, &success);
8634
if (!success)
8635
return false;
8636
8637
// R[d] = ZeroExtend(rotated<15:0>, 32);
8638
std::optional<RegisterInfo> source_reg =
8639
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
8640
8641
EmulateInstruction::Context context;
8642
context.type = eContextRegisterLoad;
8643
context.SetRegister(*source_reg);
8644
8645
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8646
Bits32(rotated, 15, 0)))
8647
return false;
8648
}
8649
return true;
8650
}
8651
8652
// RFE (Return From Exception) loads the PC and the CPSR from the word at the
8653
// specified address and the following
8654
// word respectively.
8655
bool EmulateInstructionARM::EmulateRFE(const uint32_t opcode,
8656
const ARMEncoding encoding) {
8657
#if 0
8658
if ConditionPassed() then
8659
EncodingSpecificOperations();
8660
if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8661
UNPREDICTABLE;
8662
else
8663
address = if increment then R[n] else R[n]-8;
8664
if wordhigher then address = address+4;
8665
CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
8666
BranchWritePC(MemA[address,4]);
8667
if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8668
#endif
8669
8670
bool success = false;
8671
8672
if (ConditionPassed(opcode)) {
8673
uint32_t n;
8674
bool wback;
8675
bool increment;
8676
bool wordhigher;
8677
8678
// EncodingSpecificOperations();
8679
switch (encoding) {
8680
case eEncodingT1:
8681
// n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher =
8682
// FALSE;
8683
n = Bits32(opcode, 19, 16);
8684
wback = BitIsSet(opcode, 21);
8685
increment = false;
8686
wordhigher = false;
8687
8688
// if n == 15 then UNPREDICTABLE;
8689
if (n == 15)
8690
return false;
8691
8692
// if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8693
if (InITBlock() && !LastInITBlock())
8694
return false;
8695
8696
break;
8697
8698
case eEncodingT2:
8699
// n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
8700
n = Bits32(opcode, 19, 16);
8701
wback = BitIsSet(opcode, 21);
8702
increment = true;
8703
wordhigher = false;
8704
8705
// if n == 15 then UNPREDICTABLE;
8706
if (n == 15)
8707
return false;
8708
8709
// if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8710
if (InITBlock() && !LastInITBlock())
8711
return false;
8712
8713
break;
8714
8715
case eEncodingA1:
8716
// n = UInt(Rn);
8717
n = Bits32(opcode, 19, 16);
8718
8719
// wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
8720
wback = BitIsSet(opcode, 21);
8721
increment = BitIsSet(opcode, 23);
8722
wordhigher = (Bit32(opcode, 24) == Bit32(opcode, 23));
8723
8724
// if n == 15 then UNPREDICTABLE;
8725
if (n == 15)
8726
return false;
8727
8728
break;
8729
8730
default:
8731
return false;
8732
}
8733
8734
// if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE
8735
// then
8736
if (!CurrentModeIsPrivileged())
8737
// UNPREDICTABLE;
8738
return false;
8739
else {
8740
uint64_t Rn =
8741
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8742
if (!success)
8743
return false;
8744
8745
addr_t address;
8746
// address = if increment then R[n] else R[n]-8;
8747
if (increment)
8748
address = Rn;
8749
else
8750
address = Rn - 8;
8751
8752
// if wordhigher then address = address+4;
8753
if (wordhigher)
8754
address = address + 4;
8755
8756
// CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
8757
std::optional<RegisterInfo> base_reg =
8758
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
8759
8760
EmulateInstruction::Context context;
8761
context.type = eContextReturnFromException;
8762
context.SetRegisterPlusOffset(*base_reg, address - Rn);
8763
8764
uint64_t data = MemARead(context, address + 4, 4, 0, &success);
8765
if (!success)
8766
return false;
8767
8768
CPSRWriteByInstr(data, 15, true);
8769
8770
// BranchWritePC(MemA[address,4]);
8771
uint64_t data2 = MemARead(context, address, 4, 0, &success);
8772
if (!success)
8773
return false;
8774
8775
BranchWritePC(context, data2);
8776
8777
// if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8778
if (wback) {
8779
context.type = eContextAdjustBaseRegister;
8780
if (increment) {
8781
context.SetOffset(8);
8782
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8783
Rn + 8))
8784
return false;
8785
} else {
8786
context.SetOffset(-8);
8787
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8788
Rn - 8))
8789
return false;
8790
}
8791
} // if wback
8792
}
8793
} // if ConditionPassed()
8794
return true;
8795
}
8796
8797
// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a
8798
// register value and an immediate value, and writes the result to the
8799
// destination register. It can optionally update the condition flags based on
8800
// the result.
8801
bool EmulateInstructionARM::EmulateEORImm(const uint32_t opcode,
8802
const ARMEncoding encoding) {
8803
#if 0
8804
// ARM pseudo code...
8805
if ConditionPassed() then
8806
EncodingSpecificOperations();
8807
result = R[n] EOR imm32;
8808
if d == 15 then // Can only occur for ARM encoding
8809
ALUWritePC(result); // setflags is always FALSE here
8810
else
8811
R[d] = result;
8812
if setflags then
8813
APSR.N = result<31>;
8814
APSR.Z = IsZeroBit(result);
8815
APSR.C = carry;
8816
// APSR.V unchanged
8817
#endif
8818
8819
bool success = false;
8820
8821
if (ConditionPassed(opcode)) {
8822
uint32_t Rd, Rn;
8823
uint32_t
8824
imm32; // the immediate value to be ORed to the value obtained from Rn
8825
bool setflags;
8826
uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8827
switch (encoding) {
8828
case eEncodingT1:
8829
Rd = Bits32(opcode, 11, 8);
8830
Rn = Bits32(opcode, 19, 16);
8831
setflags = BitIsSet(opcode, 20);
8832
imm32 = ThumbExpandImm_C(
8833
opcode, APSR_C,
8834
carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8835
// if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8836
if (Rd == 15 && setflags)
8837
return EmulateTEQImm(opcode, eEncodingT1);
8838
if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8839
return false;
8840
break;
8841
case eEncodingA1:
8842
Rd = Bits32(opcode, 15, 12);
8843
Rn = Bits32(opcode, 19, 16);
8844
setflags = BitIsSet(opcode, 20);
8845
imm32 =
8846
ARMExpandImm_C(opcode, APSR_C,
8847
carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8848
8849
// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
8850
// instructions;
8851
if (Rd == 15 && setflags)
8852
return EmulateSUBSPcLrEtc(opcode, encoding);
8853
break;
8854
default:
8855
return false;
8856
}
8857
8858
// Read the first operand.
8859
uint32_t val1 = ReadCoreReg(Rn, &success);
8860
if (!success)
8861
return false;
8862
8863
uint32_t result = val1 ^ imm32;
8864
8865
EmulateInstruction::Context context;
8866
context.type = EmulateInstruction::eContextImmediate;
8867
context.SetNoArgs();
8868
8869
if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8870
return false;
8871
}
8872
return true;
8873
}
8874
8875
// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a
8876
// register value and an optionally-shifted register value, and writes the
8877
// result to the destination register. It can optionally update the condition
8878
// flags based on the result.
8879
bool EmulateInstructionARM::EmulateEORReg(const uint32_t opcode,
8880
const ARMEncoding encoding) {
8881
#if 0
8882
// ARM pseudo code...
8883
if ConditionPassed() then
8884
EncodingSpecificOperations();
8885
(shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8886
result = R[n] EOR shifted;
8887
if d == 15 then // Can only occur for ARM encoding
8888
ALUWritePC(result); // setflags is always FALSE here
8889
else
8890
R[d] = result;
8891
if setflags then
8892
APSR.N = result<31>;
8893
APSR.Z = IsZeroBit(result);
8894
APSR.C = carry;
8895
// APSR.V unchanged
8896
#endif
8897
8898
bool success = false;
8899
8900
if (ConditionPassed(opcode)) {
8901
uint32_t Rd, Rn, Rm;
8902
ARM_ShifterType shift_t;
8903
uint32_t shift_n; // the shift applied to the value read from Rm
8904
bool setflags;
8905
uint32_t carry;
8906
switch (encoding) {
8907
case eEncodingT1:
8908
Rd = Rn = Bits32(opcode, 2, 0);
8909
Rm = Bits32(opcode, 5, 3);
8910
setflags = !InITBlock();
8911
shift_t = SRType_LSL;
8912
shift_n = 0;
8913
break;
8914
case eEncodingT2:
8915
Rd = Bits32(opcode, 11, 8);
8916
Rn = Bits32(opcode, 19, 16);
8917
Rm = Bits32(opcode, 3, 0);
8918
setflags = BitIsSet(opcode, 20);
8919
shift_n = DecodeImmShiftThumb(opcode, shift_t);
8920
// if Rd == '1111' && S == '1' then SEE TEQ (register);
8921
if (Rd == 15 && setflags)
8922
return EmulateTEQReg(opcode, eEncodingT1);
8923
if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8924
return false;
8925
break;
8926
case eEncodingA1:
8927
Rd = Bits32(opcode, 15, 12);
8928
Rn = Bits32(opcode, 19, 16);
8929
Rm = Bits32(opcode, 3, 0);
8930
setflags = BitIsSet(opcode, 20);
8931
shift_n = DecodeImmShiftARM(opcode, shift_t);
8932
8933
// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
8934
// instructions;
8935
if (Rd == 15 && setflags)
8936
return EmulateSUBSPcLrEtc(opcode, encoding);
8937
break;
8938
default:
8939
return false;
8940
}
8941
8942
// Read the first operand.
8943
uint32_t val1 = ReadCoreReg(Rn, &success);
8944
if (!success)
8945
return false;
8946
8947
// Read the second operand.
8948
uint32_t val2 = ReadCoreReg(Rm, &success);
8949
if (!success)
8950
return false;
8951
8952
uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
8953
if (!success)
8954
return false;
8955
uint32_t result = val1 ^ shifted;
8956
8957
EmulateInstruction::Context context;
8958
context.type = EmulateInstruction::eContextImmediate;
8959
context.SetNoArgs();
8960
8961
if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8962
return false;
8963
}
8964
return true;
8965
}
8966
8967
// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value
8968
// and an immediate value, and writes the result to the destination register.
8969
// It can optionally update the condition flags based on the result.
8970
bool EmulateInstructionARM::EmulateORRImm(const uint32_t opcode,
8971
const ARMEncoding encoding) {
8972
#if 0
8973
// ARM pseudo code...
8974
if ConditionPassed() then
8975
EncodingSpecificOperations();
8976
result = R[n] OR imm32;
8977
if d == 15 then // Can only occur for ARM encoding
8978
ALUWritePC(result); // setflags is always FALSE here
8979
else
8980
R[d] = result;
8981
if setflags then
8982
APSR.N = result<31>;
8983
APSR.Z = IsZeroBit(result);
8984
APSR.C = carry;
8985
// APSR.V unchanged
8986
#endif
8987
8988
bool success = false;
8989
8990
if (ConditionPassed(opcode)) {
8991
uint32_t Rd, Rn;
8992
uint32_t
8993
imm32; // the immediate value to be ORed to the value obtained from Rn
8994
bool setflags;
8995
uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8996
switch (encoding) {
8997
case eEncodingT1:
8998
Rd = Bits32(opcode, 11, 8);
8999
Rn = Bits32(opcode, 19, 16);
9000
setflags = BitIsSet(opcode, 20);
9001
imm32 = ThumbExpandImm_C(
9002
opcode, APSR_C,
9003
carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9004
// if Rn == '1111' then SEE MOV (immediate);
9005
if (Rn == 15)
9006
return EmulateMOVRdImm(opcode, eEncodingT2);
9007
if (BadReg(Rd) || Rn == 13)
9008
return false;
9009
break;
9010
case eEncodingA1:
9011
Rd = Bits32(opcode, 15, 12);
9012
Rn = Bits32(opcode, 19, 16);
9013
setflags = BitIsSet(opcode, 20);
9014
imm32 =
9015
ARMExpandImm_C(opcode, APSR_C,
9016
carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9017
9018
if (Rd == 15 && setflags)
9019
return EmulateSUBSPcLrEtc(opcode, encoding);
9020
break;
9021
default:
9022
return false;
9023
}
9024
9025
// Read the first operand.
9026
uint32_t val1 = ReadCoreReg(Rn, &success);
9027
if (!success)
9028
return false;
9029
9030
uint32_t result = val1 | imm32;
9031
9032
EmulateInstruction::Context context;
9033
context.type = EmulateInstruction::eContextImmediate;
9034
context.SetNoArgs();
9035
9036
if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
9037
return false;
9038
}
9039
return true;
9040
}
9041
9042
// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value
9043
// and an optionally-shifted register value, and writes the result to the
9044
// destination register. It can optionally update the condition flags based on
9045
// the result.
9046
bool EmulateInstructionARM::EmulateORRReg(const uint32_t opcode,
9047
const ARMEncoding encoding) {
9048
#if 0
9049
// ARM pseudo code...
9050
if ConditionPassed() then
9051
EncodingSpecificOperations();
9052
(shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9053
result = R[n] OR shifted;
9054
if d == 15 then // Can only occur for ARM encoding
9055
ALUWritePC(result); // setflags is always FALSE here
9056
else
9057
R[d] = result;
9058
if setflags then
9059
APSR.N = result<31>;
9060
APSR.Z = IsZeroBit(result);
9061
APSR.C = carry;
9062
// APSR.V unchanged
9063
#endif
9064
9065
bool success = false;
9066
9067
if (ConditionPassed(opcode)) {
9068
uint32_t Rd, Rn, Rm;
9069
ARM_ShifterType shift_t;
9070
uint32_t shift_n; // the shift applied to the value read from Rm
9071
bool setflags;
9072
uint32_t carry;
9073
switch (encoding) {
9074
case eEncodingT1:
9075
Rd = Rn = Bits32(opcode, 2, 0);
9076
Rm = Bits32(opcode, 5, 3);
9077
setflags = !InITBlock();
9078
shift_t = SRType_LSL;
9079
shift_n = 0;
9080
break;
9081
case eEncodingT2:
9082
Rd = Bits32(opcode, 11, 8);
9083
Rn = Bits32(opcode, 19, 16);
9084
Rm = Bits32(opcode, 3, 0);
9085
setflags = BitIsSet(opcode, 20);
9086
shift_n = DecodeImmShiftThumb(opcode, shift_t);
9087
// if Rn == '1111' then SEE MOV (register);
9088
if (Rn == 15)
9089
return EmulateMOVRdRm(opcode, eEncodingT3);
9090
if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
9091
return false;
9092
break;
9093
case eEncodingA1:
9094
Rd = Bits32(opcode, 15, 12);
9095
Rn = Bits32(opcode, 19, 16);
9096
Rm = Bits32(opcode, 3, 0);
9097
setflags = BitIsSet(opcode, 20);
9098
shift_n = DecodeImmShiftARM(opcode, shift_t);
9099
9100
if (Rd == 15 && setflags)
9101
return EmulateSUBSPcLrEtc(opcode, encoding);
9102
break;
9103
default:
9104
return false;
9105
}
9106
9107
// Read the first operand.
9108
uint32_t val1 = ReadCoreReg(Rn, &success);
9109
if (!success)
9110
return false;
9111
9112
// Read the second operand.
9113
uint32_t val2 = ReadCoreReg(Rm, &success);
9114
if (!success)
9115
return false;
9116
9117
uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9118
if (!success)
9119
return false;
9120
uint32_t result = val1 | shifted;
9121
9122
EmulateInstruction::Context context;
9123
context.type = EmulateInstruction::eContextImmediate;
9124
context.SetNoArgs();
9125
9126
if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
9127
return false;
9128
}
9129
return true;
9130
}
9131
9132
// Reverse Subtract (immediate) subtracts a register value from an immediate
9133
// value, and writes the result to the destination register. It can optionally
9134
// update the condition flags based on the result.
9135
bool EmulateInstructionARM::EmulateRSBImm(const uint32_t opcode,
9136
const ARMEncoding encoding) {
9137
#if 0
9138
// ARM pseudo code...
9139
if ConditionPassed() then
9140
EncodingSpecificOperations();
9141
(result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
9142
if d == 15 then // Can only occur for ARM encoding
9143
ALUWritePC(result); // setflags is always FALSE here
9144
else
9145
R[d] = result;
9146
if setflags then
9147
APSR.N = result<31>;
9148
APSR.Z = IsZeroBit(result);
9149
APSR.C = carry;
9150
APSR.V = overflow;
9151
#endif
9152
9153
bool success = false;
9154
9155
uint32_t Rd; // the destination register
9156
uint32_t Rn; // the first operand
9157
bool setflags;
9158
uint32_t
9159
imm32; // the immediate value to be added to the value obtained from Rn
9160
switch (encoding) {
9161
case eEncodingT1:
9162
Rd = Bits32(opcode, 2, 0);
9163
Rn = Bits32(opcode, 5, 3);
9164
setflags = !InITBlock();
9165
imm32 = 0;
9166
break;
9167
case eEncodingT2:
9168
Rd = Bits32(opcode, 11, 8);
9169
Rn = Bits32(opcode, 19, 16);
9170
setflags = BitIsSet(opcode, 20);
9171
imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9172
if (BadReg(Rd) || BadReg(Rn))
9173
return false;
9174
break;
9175
case eEncodingA1:
9176
Rd = Bits32(opcode, 15, 12);
9177
Rn = Bits32(opcode, 19, 16);
9178
setflags = BitIsSet(opcode, 20);
9179
imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9180
9181
// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9182
// instructions;
9183
if (Rd == 15 && setflags)
9184
return EmulateSUBSPcLrEtc(opcode, encoding);
9185
break;
9186
default:
9187
return false;
9188
}
9189
// Read the register value from the operand register Rn.
9190
uint32_t reg_val = ReadCoreReg(Rn, &success);
9191
if (!success)
9192
return false;
9193
9194
AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
9195
9196
EmulateInstruction::Context context;
9197
context.type = EmulateInstruction::eContextImmediate;
9198
context.SetNoArgs();
9199
9200
return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9201
res.carry_out, res.overflow);
9202
}
9203
9204
// Reverse Subtract (register) subtracts a register value from an optionally-
9205
// shifted register value, and writes the result to the destination register.
9206
// It can optionally update the condition flags based on the result.
9207
bool EmulateInstructionARM::EmulateRSBReg(const uint32_t opcode,
9208
const ARMEncoding encoding) {
9209
#if 0
9210
// ARM pseudo code...
9211
if ConditionPassed() then
9212
EncodingSpecificOperations();
9213
shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9214
(result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
9215
if d == 15 then // Can only occur for ARM encoding
9216
ALUWritePC(result); // setflags is always FALSE here
9217
else
9218
R[d] = result;
9219
if setflags then
9220
APSR.N = result<31>;
9221
APSR.Z = IsZeroBit(result);
9222
APSR.C = carry;
9223
APSR.V = overflow;
9224
#endif
9225
9226
bool success = false;
9227
9228
uint32_t Rd; // the destination register
9229
uint32_t Rn; // the first operand
9230
uint32_t Rm; // the second operand
9231
bool setflags;
9232
ARM_ShifterType shift_t;
9233
uint32_t shift_n; // the shift applied to the value read from Rm
9234
switch (encoding) {
9235
case eEncodingT1:
9236
Rd = Bits32(opcode, 11, 8);
9237
Rn = Bits32(opcode, 19, 16);
9238
Rm = Bits32(opcode, 3, 0);
9239
setflags = BitIsSet(opcode, 20);
9240
shift_n = DecodeImmShiftThumb(opcode, shift_t);
9241
// if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
9242
if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
9243
return false;
9244
break;
9245
case eEncodingA1:
9246
Rd = Bits32(opcode, 15, 12);
9247
Rn = Bits32(opcode, 19, 16);
9248
Rm = Bits32(opcode, 3, 0);
9249
setflags = BitIsSet(opcode, 20);
9250
shift_n = DecodeImmShiftARM(opcode, shift_t);
9251
9252
// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9253
// instructions;
9254
if (Rd == 15 && setflags)
9255
return EmulateSUBSPcLrEtc(opcode, encoding);
9256
break;
9257
default:
9258
return false;
9259
}
9260
// Read the register value from register Rn.
9261
uint32_t val1 = ReadCoreReg(Rn, &success);
9262
if (!success)
9263
return false;
9264
9265
// Read the register value from register Rm.
9266
uint32_t val2 = ReadCoreReg(Rm, &success);
9267
if (!success)
9268
return false;
9269
9270
uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
9271
if (!success)
9272
return false;
9273
AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
9274
9275
EmulateInstruction::Context context;
9276
context.type = EmulateInstruction::eContextImmediate;
9277
context.SetNoArgs();
9278
return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9279
res.carry_out, res.overflow);
9280
}
9281
9282
// Reverse Subtract with Carry (immediate) subtracts a register value and the
9283
// value of NOT (Carry flag) from an immediate value, and writes the result to
9284
// the destination register. It can optionally update the condition flags based
9285
// on the result.
9286
bool EmulateInstructionARM::EmulateRSCImm(const uint32_t opcode,
9287
const ARMEncoding encoding) {
9288
#if 0
9289
// ARM pseudo code...
9290
if ConditionPassed() then
9291
EncodingSpecificOperations();
9292
(result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
9293
if d == 15 then
9294
ALUWritePC(result); // setflags is always FALSE here
9295
else
9296
R[d] = result;
9297
if setflags then
9298
APSR.N = result<31>;
9299
APSR.Z = IsZeroBit(result);
9300
APSR.C = carry;
9301
APSR.V = overflow;
9302
#endif
9303
9304
bool success = false;
9305
9306
uint32_t Rd; // the destination register
9307
uint32_t Rn; // the first operand
9308
bool setflags;
9309
uint32_t
9310
imm32; // the immediate value to be added to the value obtained from Rn
9311
switch (encoding) {
9312
case eEncodingA1:
9313
Rd = Bits32(opcode, 15, 12);
9314
Rn = Bits32(opcode, 19, 16);
9315
setflags = BitIsSet(opcode, 20);
9316
imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9317
9318
// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9319
// instructions;
9320
if (Rd == 15 && setflags)
9321
return EmulateSUBSPcLrEtc(opcode, encoding);
9322
break;
9323
default:
9324
return false;
9325
}
9326
// Read the register value from the operand register Rn.
9327
uint32_t reg_val = ReadCoreReg(Rn, &success);
9328
if (!success)
9329
return false;
9330
9331
AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
9332
9333
EmulateInstruction::Context context;
9334
context.type = EmulateInstruction::eContextImmediate;
9335
context.SetNoArgs();
9336
9337
return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9338
res.carry_out, res.overflow);
9339
}
9340
9341
// Reverse Subtract with Carry (register) subtracts a register value and the
9342
// value of NOT (Carry flag) from an optionally-shifted register value, and
9343
// writes the result to the destination register. It can optionally update the
9344
// condition flags based on the result.
9345
bool EmulateInstructionARM::EmulateRSCReg(const uint32_t opcode,
9346
const ARMEncoding encoding) {
9347
#if 0
9348
// ARM pseudo code...
9349
if ConditionPassed() then
9350
EncodingSpecificOperations();
9351
shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9352
(result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
9353
if d == 15 then
9354
ALUWritePC(result); // setflags is always FALSE here
9355
else
9356
R[d] = result;
9357
if setflags then
9358
APSR.N = result<31>;
9359
APSR.Z = IsZeroBit(result);
9360
APSR.C = carry;
9361
APSR.V = overflow;
9362
#endif
9363
9364
bool success = false;
9365
9366
uint32_t Rd; // the destination register
9367
uint32_t Rn; // the first operand
9368
uint32_t Rm; // the second operand
9369
bool setflags;
9370
ARM_ShifterType shift_t;
9371
uint32_t shift_n; // the shift applied to the value read from Rm
9372
switch (encoding) {
9373
case eEncodingA1:
9374
Rd = Bits32(opcode, 15, 12);
9375
Rn = Bits32(opcode, 19, 16);
9376
Rm = Bits32(opcode, 3, 0);
9377
setflags = BitIsSet(opcode, 20);
9378
shift_n = DecodeImmShiftARM(opcode, shift_t);
9379
9380
// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9381
// instructions;
9382
if (Rd == 15 && setflags)
9383
return EmulateSUBSPcLrEtc(opcode, encoding);
9384
break;
9385
default:
9386
return false;
9387
}
9388
// Read the register value from register Rn.
9389
uint32_t val1 = ReadCoreReg(Rn, &success);
9390
if (!success)
9391
return false;
9392
9393
// Read the register value from register Rm.
9394
uint32_t val2 = ReadCoreReg(Rm, &success);
9395
if (!success)
9396
return false;
9397
9398
uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
9399
if (!success)
9400
return false;
9401
AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
9402
9403
EmulateInstruction::Context context;
9404
context.type = EmulateInstruction::eContextImmediate;
9405
context.SetNoArgs();
9406
return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9407
res.carry_out, res.overflow);
9408
}
9409
9410
// Subtract with Carry (immediate) subtracts an immediate value and the value
9411
// of
9412
// NOT (Carry flag) from a register value, and writes the result to the
9413
// destination register.
9414
// It can optionally update the condition flags based on the result.
9415
bool EmulateInstructionARM::EmulateSBCImm(const uint32_t opcode,
9416
const ARMEncoding encoding) {
9417
#if 0
9418
// ARM pseudo code...
9419
if ConditionPassed() then
9420
EncodingSpecificOperations();
9421
(result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
9422
if d == 15 then // Can only occur for ARM encoding
9423
ALUWritePC(result); // setflags is always FALSE here
9424
else
9425
R[d] = result;
9426
if setflags then
9427
APSR.N = result<31>;
9428
APSR.Z = IsZeroBit(result);
9429
APSR.C = carry;
9430
APSR.V = overflow;
9431
#endif
9432
9433
bool success = false;
9434
9435
uint32_t Rd; // the destination register
9436
uint32_t Rn; // the first operand
9437
bool setflags;
9438
uint32_t
9439
imm32; // the immediate value to be added to the value obtained from Rn
9440
switch (encoding) {
9441
case eEncodingT1:
9442
Rd = Bits32(opcode, 11, 8);
9443
Rn = Bits32(opcode, 19, 16);
9444
setflags = BitIsSet(opcode, 20);
9445
imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9446
if (BadReg(Rd) || BadReg(Rn))
9447
return false;
9448
break;
9449
case eEncodingA1:
9450
Rd = Bits32(opcode, 15, 12);
9451
Rn = Bits32(opcode, 19, 16);
9452
setflags = BitIsSet(opcode, 20);
9453
imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9454
9455
// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9456
// instructions;
9457
if (Rd == 15 && setflags)
9458
return EmulateSUBSPcLrEtc(opcode, encoding);
9459
break;
9460
default:
9461
return false;
9462
}
9463
// Read the register value from the operand register Rn.
9464
uint32_t reg_val = ReadCoreReg(Rn, &success);
9465
if (!success)
9466
return false;
9467
9468
AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
9469
9470
EmulateInstruction::Context context;
9471
context.type = EmulateInstruction::eContextImmediate;
9472
context.SetNoArgs();
9473
9474
return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9475
res.carry_out, res.overflow);
9476
}
9477
9478
// Subtract with Carry (register) subtracts an optionally-shifted register
9479
// value and the value of
9480
// NOT (Carry flag) from a register value, and writes the result to the
9481
// destination register.
9482
// It can optionally update the condition flags based on the result.
9483
bool EmulateInstructionARM::EmulateSBCReg(const uint32_t opcode,
9484
const ARMEncoding encoding) {
9485
#if 0
9486
// ARM pseudo code...
9487
if ConditionPassed() then
9488
EncodingSpecificOperations();
9489
shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9490
(result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
9491
if d == 15 then // Can only occur for ARM encoding
9492
ALUWritePC(result); // setflags is always FALSE here
9493
else
9494
R[d] = result;
9495
if setflags then
9496
APSR.N = result<31>;
9497
APSR.Z = IsZeroBit(result);
9498
APSR.C = carry;
9499
APSR.V = overflow;
9500
#endif
9501
9502
bool success = false;
9503
9504
uint32_t Rd; // the destination register
9505
uint32_t Rn; // the first operand
9506
uint32_t Rm; // the second operand
9507
bool setflags;
9508
ARM_ShifterType shift_t;
9509
uint32_t shift_n; // the shift applied to the value read from Rm
9510
switch (encoding) {
9511
case eEncodingT1:
9512
Rd = Rn = Bits32(opcode, 2, 0);
9513
Rm = Bits32(opcode, 5, 3);
9514
setflags = !InITBlock();
9515
shift_t = SRType_LSL;
9516
shift_n = 0;
9517
break;
9518
case eEncodingT2:
9519
Rd = Bits32(opcode, 11, 8);
9520
Rn = Bits32(opcode, 19, 16);
9521
Rm = Bits32(opcode, 3, 0);
9522
setflags = BitIsSet(opcode, 20);
9523
shift_n = DecodeImmShiftThumb(opcode, shift_t);
9524
if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
9525
return false;
9526
break;
9527
case eEncodingA1:
9528
Rd = Bits32(opcode, 15, 12);
9529
Rn = Bits32(opcode, 19, 16);
9530
Rm = Bits32(opcode, 3, 0);
9531
setflags = BitIsSet(opcode, 20);
9532
shift_n = DecodeImmShiftARM(opcode, shift_t);
9533
9534
// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9535
// instructions;
9536
if (Rd == 15 && setflags)
9537
return EmulateSUBSPcLrEtc(opcode, encoding);
9538
break;
9539
default:
9540
return false;
9541
}
9542
// Read the register value from register Rn.
9543
uint32_t val1 = ReadCoreReg(Rn, &success);
9544
if (!success)
9545
return false;
9546
9547
// Read the register value from register Rm.
9548
uint32_t val2 = ReadCoreReg(Rm, &success);
9549
if (!success)
9550
return false;
9551
9552
uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
9553
if (!success)
9554
return false;
9555
AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
9556
9557
EmulateInstruction::Context context;
9558
context.type = EmulateInstruction::eContextImmediate;
9559
context.SetNoArgs();
9560
return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9561
res.carry_out, res.overflow);
9562
}
9563
9564
// This instruction subtracts an immediate value from a register value, and
9565
// writes the result to the destination register. It can optionally update the
9566
// condition flags based on the result.
9567
bool EmulateInstructionARM::EmulateSUBImmThumb(const uint32_t opcode,
9568
const ARMEncoding encoding) {
9569
#if 0
9570
// ARM pseudo code...
9571
if ConditionPassed() then
9572
EncodingSpecificOperations();
9573
(result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9574
R[d] = result;
9575
if setflags then
9576
APSR.N = result<31>;
9577
APSR.Z = IsZeroBit(result);
9578
APSR.C = carry;
9579
APSR.V = overflow;
9580
#endif
9581
9582
bool success = false;
9583
9584
uint32_t Rd; // the destination register
9585
uint32_t Rn; // the first operand
9586
bool setflags;
9587
uint32_t imm32; // the immediate value to be subtracted from the value
9588
// obtained from Rn
9589
switch (encoding) {
9590
case eEncodingT1:
9591
Rd = Bits32(opcode, 2, 0);
9592
Rn = Bits32(opcode, 5, 3);
9593
setflags = !InITBlock();
9594
imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
9595
break;
9596
case eEncodingT2:
9597
Rd = Rn = Bits32(opcode, 10, 8);
9598
setflags = !InITBlock();
9599
imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
9600
break;
9601
case eEncodingT3:
9602
Rd = Bits32(opcode, 11, 8);
9603
Rn = Bits32(opcode, 19, 16);
9604
setflags = BitIsSet(opcode, 20);
9605
imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9606
9607
// if Rd == '1111' && S == '1' then SEE CMP (immediate);
9608
if (Rd == 15 && setflags)
9609
return EmulateCMPImm(opcode, eEncodingT2);
9610
9611
// if Rn == '1101' then SEE SUB (SP minus immediate);
9612
if (Rn == 13)
9613
return EmulateSUBSPImm(opcode, eEncodingT2);
9614
9615
// if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
9616
if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
9617
return false;
9618
break;
9619
case eEncodingT4:
9620
Rd = Bits32(opcode, 11, 8);
9621
Rn = Bits32(opcode, 19, 16);
9622
setflags = BitIsSet(opcode, 20);
9623
imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
9624
9625
// if Rn == '1111' then SEE ADR;
9626
if (Rn == 15)
9627
return EmulateADR(opcode, eEncodingT2);
9628
9629
// if Rn == '1101' then SEE SUB (SP minus immediate);
9630
if (Rn == 13)
9631
return EmulateSUBSPImm(opcode, eEncodingT3);
9632
9633
if (BadReg(Rd))
9634
return false;
9635
break;
9636
default:
9637
return false;
9638
}
9639
// Read the register value from the operand register Rn.
9640
uint32_t reg_val = ReadCoreReg(Rn, &success);
9641
if (!success)
9642
return false;
9643
9644
AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9645
9646
EmulateInstruction::Context context;
9647
context.type = EmulateInstruction::eContextImmediate;
9648
context.SetNoArgs();
9649
9650
return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9651
res.carry_out, res.overflow);
9652
}
9653
9654
// This instruction subtracts an immediate value from a register value, and
9655
// writes the result to the destination register. It can optionally update the
9656
// condition flags based on the result.
9657
bool EmulateInstructionARM::EmulateSUBImmARM(const uint32_t opcode,
9658
const ARMEncoding encoding) {
9659
#if 0
9660
// ARM pseudo code...
9661
if ConditionPassed() then
9662
EncodingSpecificOperations();
9663
(result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9664
if d == 15 then
9665
ALUWritePC(result); // setflags is always FALSE here
9666
else
9667
R[d] = result;
9668
if setflags then
9669
APSR.N = result<31>;
9670
APSR.Z = IsZeroBit(result);
9671
APSR.C = carry;
9672
APSR.V = overflow;
9673
#endif
9674
9675
bool success = false;
9676
9677
if (ConditionPassed(opcode)) {
9678
uint32_t Rd; // the destination register
9679
uint32_t Rn; // the first operand
9680
bool setflags;
9681
uint32_t imm32; // the immediate value to be subtracted from the value
9682
// obtained from Rn
9683
switch (encoding) {
9684
case eEncodingA1:
9685
Rd = Bits32(opcode, 15, 12);
9686
Rn = Bits32(opcode, 19, 16);
9687
setflags = BitIsSet(opcode, 20);
9688
imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9689
9690
// if Rn == '1111' && S == '0' then SEE ADR;
9691
if (Rn == 15 && !setflags)
9692
return EmulateADR(opcode, eEncodingA2);
9693
9694
// if Rn == '1101' then SEE SUB (SP minus immediate);
9695
if (Rn == 13)
9696
return EmulateSUBSPImm(opcode, eEncodingA1);
9697
9698
// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9699
// instructions;
9700
if (Rd == 15 && setflags)
9701
return EmulateSUBSPcLrEtc(opcode, encoding);
9702
break;
9703
default:
9704
return false;
9705
}
9706
// Read the register value from the operand register Rn.
9707
uint32_t reg_val = ReadCoreReg(Rn, &success);
9708
if (!success)
9709
return false;
9710
9711
AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9712
9713
EmulateInstruction::Context context;
9714
if (Rd == 13)
9715
context.type = EmulateInstruction::eContextAdjustStackPointer;
9716
else
9717
context.type = EmulateInstruction::eContextRegisterPlusOffset;
9718
9719
std::optional<RegisterInfo> dwarf_reg =
9720
GetRegisterInfo(eRegisterKindDWARF, Rn);
9721
int64_t imm32_signed = imm32;
9722
context.SetRegisterPlusOffset(*dwarf_reg, -imm32_signed);
9723
9724
if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9725
res.carry_out, res.overflow))
9726
return false;
9727
}
9728
return true;
9729
}
9730
9731
// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a
9732
// register value and an immediate value. It updates the condition flags based
9733
// on the result, and discards the result.
9734
bool EmulateInstructionARM::EmulateTEQImm(const uint32_t opcode,
9735
const ARMEncoding encoding) {
9736
#if 0
9737
// ARM pseudo code...
9738
if ConditionPassed() then
9739
EncodingSpecificOperations();
9740
result = R[n] EOR imm32;
9741
APSR.N = result<31>;
9742
APSR.Z = IsZeroBit(result);
9743
APSR.C = carry;
9744
// APSR.V unchanged
9745
#endif
9746
9747
bool success = false;
9748
9749
if (ConditionPassed(opcode)) {
9750
uint32_t Rn;
9751
uint32_t
9752
imm32; // the immediate value to be ANDed to the value obtained from Rn
9753
uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9754
switch (encoding) {
9755
case eEncodingT1:
9756
Rn = Bits32(opcode, 19, 16);
9757
imm32 = ThumbExpandImm_C(
9758
opcode, APSR_C,
9759
carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9760
if (BadReg(Rn))
9761
return false;
9762
break;
9763
case eEncodingA1:
9764
Rn = Bits32(opcode, 19, 16);
9765
imm32 =
9766
ARMExpandImm_C(opcode, APSR_C,
9767
carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9768
break;
9769
default:
9770
return false;
9771
}
9772
9773
// Read the first operand.
9774
uint32_t val1 = ReadCoreReg(Rn, &success);
9775
if (!success)
9776
return false;
9777
9778
uint32_t result = val1 ^ imm32;
9779
9780
EmulateInstruction::Context context;
9781
context.type = EmulateInstruction::eContextImmediate;
9782
context.SetNoArgs();
9783
9784
if (!WriteFlags(context, result, carry))
9785
return false;
9786
}
9787
return true;
9788
}
9789
9790
// Test Equivalence (register) performs a bitwise exclusive OR operation on a
9791
// register value and an optionally-shifted register value. It updates the
9792
// condition flags based on the result, and discards the result.
9793
bool EmulateInstructionARM::EmulateTEQReg(const uint32_t opcode,
9794
const ARMEncoding encoding) {
9795
#if 0
9796
// ARM pseudo code...
9797
if ConditionPassed() then
9798
EncodingSpecificOperations();
9799
(shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9800
result = R[n] EOR shifted;
9801
APSR.N = result<31>;
9802
APSR.Z = IsZeroBit(result);
9803
APSR.C = carry;
9804
// APSR.V unchanged
9805
#endif
9806
9807
bool success = false;
9808
9809
if (ConditionPassed(opcode)) {
9810
uint32_t Rn, Rm;
9811
ARM_ShifterType shift_t;
9812
uint32_t shift_n; // the shift applied to the value read from Rm
9813
uint32_t carry;
9814
switch (encoding) {
9815
case eEncodingT1:
9816
Rn = Bits32(opcode, 19, 16);
9817
Rm = Bits32(opcode, 3, 0);
9818
shift_n = DecodeImmShiftThumb(opcode, shift_t);
9819
if (BadReg(Rn) || BadReg(Rm))
9820
return false;
9821
break;
9822
case eEncodingA1:
9823
Rn = Bits32(opcode, 19, 16);
9824
Rm = Bits32(opcode, 3, 0);
9825
shift_n = DecodeImmShiftARM(opcode, shift_t);
9826
break;
9827
default:
9828
return false;
9829
}
9830
9831
// Read the first operand.
9832
uint32_t val1 = ReadCoreReg(Rn, &success);
9833
if (!success)
9834
return false;
9835
9836
// Read the second operand.
9837
uint32_t val2 = ReadCoreReg(Rm, &success);
9838
if (!success)
9839
return false;
9840
9841
uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9842
if (!success)
9843
return false;
9844
uint32_t result = val1 ^ shifted;
9845
9846
EmulateInstruction::Context context;
9847
context.type = EmulateInstruction::eContextImmediate;
9848
context.SetNoArgs();
9849
9850
if (!WriteFlags(context, result, carry))
9851
return false;
9852
}
9853
return true;
9854
}
9855
9856
// Test (immediate) performs a bitwise AND operation on a register value and an
9857
// immediate value. It updates the condition flags based on the result, and
9858
// discards the result.
9859
bool EmulateInstructionARM::EmulateTSTImm(const uint32_t opcode,
9860
const ARMEncoding encoding) {
9861
#if 0
9862
// ARM pseudo code...
9863
if ConditionPassed() then
9864
EncodingSpecificOperations();
9865
result = R[n] AND imm32;
9866
APSR.N = result<31>;
9867
APSR.Z = IsZeroBit(result);
9868
APSR.C = carry;
9869
// APSR.V unchanged
9870
#endif
9871
9872
bool success = false;
9873
9874
if (ConditionPassed(opcode)) {
9875
uint32_t Rn;
9876
uint32_t
9877
imm32; // the immediate value to be ANDed to the value obtained from Rn
9878
uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9879
switch (encoding) {
9880
case eEncodingT1:
9881
Rn = Bits32(opcode, 19, 16);
9882
imm32 = ThumbExpandImm_C(
9883
opcode, APSR_C,
9884
carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9885
if (BadReg(Rn))
9886
return false;
9887
break;
9888
case eEncodingA1:
9889
Rn = Bits32(opcode, 19, 16);
9890
imm32 =
9891
ARMExpandImm_C(opcode, APSR_C,
9892
carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9893
break;
9894
default:
9895
return false;
9896
}
9897
9898
// Read the first operand.
9899
uint32_t val1 = ReadCoreReg(Rn, &success);
9900
if (!success)
9901
return false;
9902
9903
uint32_t result = val1 & imm32;
9904
9905
EmulateInstruction::Context context;
9906
context.type = EmulateInstruction::eContextImmediate;
9907
context.SetNoArgs();
9908
9909
if (!WriteFlags(context, result, carry))
9910
return false;
9911
}
9912
return true;
9913
}
9914
9915
// Test (register) performs a bitwise AND operation on a register value and an
9916
// optionally-shifted register value. It updates the condition flags based on
9917
// the result, and discards the result.
9918
bool EmulateInstructionARM::EmulateTSTReg(const uint32_t opcode,
9919
const ARMEncoding encoding) {
9920
#if 0
9921
// ARM pseudo code...
9922
if ConditionPassed() then
9923
EncodingSpecificOperations();
9924
(shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9925
result = R[n] AND shifted;
9926
APSR.N = result<31>;
9927
APSR.Z = IsZeroBit(result);
9928
APSR.C = carry;
9929
// APSR.V unchanged
9930
#endif
9931
9932
bool success = false;
9933
9934
if (ConditionPassed(opcode)) {
9935
uint32_t Rn, Rm;
9936
ARM_ShifterType shift_t;
9937
uint32_t shift_n; // the shift applied to the value read from Rm
9938
uint32_t carry;
9939
switch (encoding) {
9940
case eEncodingT1:
9941
Rn = Bits32(opcode, 2, 0);
9942
Rm = Bits32(opcode, 5, 3);
9943
shift_t = SRType_LSL;
9944
shift_n = 0;
9945
break;
9946
case eEncodingT2:
9947
Rn = Bits32(opcode, 19, 16);
9948
Rm = Bits32(opcode, 3, 0);
9949
shift_n = DecodeImmShiftThumb(opcode, shift_t);
9950
if (BadReg(Rn) || BadReg(Rm))
9951
return false;
9952
break;
9953
case eEncodingA1:
9954
Rn = Bits32(opcode, 19, 16);
9955
Rm = Bits32(opcode, 3, 0);
9956
shift_n = DecodeImmShiftARM(opcode, shift_t);
9957
break;
9958
default:
9959
return false;
9960
}
9961
9962
// Read the first operand.
9963
uint32_t val1 = ReadCoreReg(Rn, &success);
9964
if (!success)
9965
return false;
9966
9967
// Read the second operand.
9968
uint32_t val2 = ReadCoreReg(Rm, &success);
9969
if (!success)
9970
return false;
9971
9972
uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9973
if (!success)
9974
return false;
9975
uint32_t result = val1 & shifted;
9976
9977
EmulateInstruction::Context context;
9978
context.type = EmulateInstruction::eContextImmediate;
9979
context.SetNoArgs();
9980
9981
if (!WriteFlags(context, result, carry))
9982
return false;
9983
}
9984
return true;
9985
}
9986
9987
// A8.6.216 SUB (SP minus register)
9988
bool EmulateInstructionARM::EmulateSUBSPReg(const uint32_t opcode,
9989
const ARMEncoding encoding) {
9990
#if 0
9991
if ConditionPassed() then
9992
EncodingSpecificOperations();
9993
shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9994
(result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');
9995
if d == 15 then // Can only occur for ARM encoding
9996
ALUWritePC(result); // setflags is always FALSE here
9997
else
9998
R[d] = result;
9999
if setflags then
10000
APSR.N = result<31>;
10001
APSR.Z = IsZeroBit(result);
10002
APSR.C = carry;
10003
APSR.V = overflow;
10004
#endif
10005
10006
bool success = false;
10007
10008
if (ConditionPassed(opcode)) {
10009
uint32_t d;
10010
uint32_t m;
10011
bool setflags;
10012
ARM_ShifterType shift_t;
10013
uint32_t shift_n;
10014
10015
switch (encoding) {
10016
case eEncodingT1:
10017
// d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
10018
d = Bits32(opcode, 11, 8);
10019
m = Bits32(opcode, 3, 0);
10020
setflags = BitIsSet(opcode, 20);
10021
10022
// (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
10023
shift_n = DecodeImmShiftThumb(opcode, shift_t);
10024
10025
// if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then
10026
// UNPREDICTABLE;
10027
if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
10028
return false;
10029
10030
// if d == 15 || BadReg(m) then UNPREDICTABLE;
10031
if ((d == 15) || BadReg(m))
10032
return false;
10033
break;
10034
10035
case eEncodingA1:
10036
// d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
10037
d = Bits32(opcode, 15, 12);
10038
m = Bits32(opcode, 3, 0);
10039
setflags = BitIsSet(opcode, 20);
10040
10041
// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
10042
// instructions;
10043
if (d == 15 && setflags)
10044
EmulateSUBSPcLrEtc(opcode, encoding);
10045
10046
// (shift_t, shift_n) = DecodeImmShift(type, imm5);
10047
shift_n = DecodeImmShiftARM(opcode, shift_t);
10048
break;
10049
10050
default:
10051
return false;
10052
}
10053
10054
// shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10055
uint32_t Rm = ReadCoreReg(m, &success);
10056
if (!success)
10057
return false;
10058
10059
uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);
10060
if (!success)
10061
return false;
10062
10063
// (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');
10064
uint32_t sp_val = ReadCoreReg(SP_REG, &success);
10065
if (!success)
10066
return false;
10067
10068
AddWithCarryResult res = AddWithCarry(sp_val, ~shifted, 1);
10069
10070
EmulateInstruction::Context context;
10071
context.type = eContextArithmetic;
10072
std::optional<RegisterInfo> sp_reg =
10073
GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);
10074
std::optional<RegisterInfo> dwarf_reg =
10075
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
10076
context.SetRegisterRegisterOperands(*sp_reg, *dwarf_reg);
10077
10078
if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags,
10079
res.carry_out, res.overflow))
10080
return false;
10081
}
10082
return true;
10083
}
10084
10085
// A8.6.7 ADD (register-shifted register)
10086
bool EmulateInstructionARM::EmulateADDRegShift(const uint32_t opcode,
10087
const ARMEncoding encoding) {
10088
#if 0
10089
if ConditionPassed() then
10090
EncodingSpecificOperations();
10091
shift_n = UInt(R[s]<7:0>);
10092
shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10093
(result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
10094
R[d] = result;
10095
if setflags then
10096
APSR.N = result<31>;
10097
APSR.Z = IsZeroBit(result);
10098
APSR.C = carry;
10099
APSR.V = overflow;
10100
#endif
10101
10102
bool success = false;
10103
10104
if (ConditionPassed(opcode)) {
10105
uint32_t d;
10106
uint32_t n;
10107
uint32_t m;
10108
uint32_t s;
10109
bool setflags;
10110
ARM_ShifterType shift_t;
10111
10112
switch (encoding) {
10113
case eEncodingA1:
10114
// d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
10115
d = Bits32(opcode, 15, 12);
10116
n = Bits32(opcode, 19, 16);
10117
m = Bits32(opcode, 3, 0);
10118
s = Bits32(opcode, 11, 8);
10119
10120
// setflags = (S == '1'); shift_t = DecodeRegShift(type);
10121
setflags = BitIsSet(opcode, 20);
10122
shift_t = DecodeRegShift(Bits32(opcode, 6, 5));
10123
10124
// if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
10125
if ((d == 15) || (n == 15) || (m == 15) || (s == 15))
10126
return false;
10127
break;
10128
10129
default:
10130
return false;
10131
}
10132
10133
// shift_n = UInt(R[s]<7:0>);
10134
uint32_t Rs = ReadCoreReg(s, &success);
10135
if (!success)
10136
return false;
10137
10138
uint32_t shift_n = Bits32(Rs, 7, 0);
10139
10140
// shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10141
uint32_t Rm = ReadCoreReg(m, &success);
10142
if (!success)
10143
return false;
10144
10145
uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);
10146
if (!success)
10147
return false;
10148
10149
// (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
10150
uint32_t Rn = ReadCoreReg(n, &success);
10151
if (!success)
10152
return false;
10153
10154
AddWithCarryResult res = AddWithCarry(Rn, shifted, 0);
10155
10156
// R[d] = result;
10157
EmulateInstruction::Context context;
10158
context.type = eContextArithmetic;
10159
std::optional<RegisterInfo> reg_n =
10160
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
10161
std::optional<RegisterInfo> reg_m =
10162
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
10163
10164
context.SetRegisterRegisterOperands(*reg_n, *reg_m);
10165
10166
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
10167
res.result))
10168
return false;
10169
10170
// if setflags then
10171
// APSR.N = result<31>;
10172
// APSR.Z = IsZeroBit(result);
10173
// APSR.C = carry;
10174
// APSR.V = overflow;
10175
if (setflags)
10176
return WriteFlags(context, res.result, res.carry_out, res.overflow);
10177
}
10178
return true;
10179
}
10180
10181
// A8.6.213 SUB (register)
10182
bool EmulateInstructionARM::EmulateSUBReg(const uint32_t opcode,
10183
const ARMEncoding encoding) {
10184
#if 0
10185
if ConditionPassed() then
10186
EncodingSpecificOperations();
10187
shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10188
(result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
10189
if d == 15 then // Can only occur for ARM encoding
10190
ALUWritePC(result); // setflags is always FALSE here
10191
else
10192
R[d] = result;
10193
if setflags then
10194
APSR.N = result<31>;
10195
APSR.Z = IsZeroBit(result);
10196
APSR.C = carry;
10197
APSR.V = overflow;
10198
#endif
10199
10200
bool success = false;
10201
10202
if (ConditionPassed(opcode)) {
10203
uint32_t d;
10204
uint32_t n;
10205
uint32_t m;
10206
bool setflags;
10207
ARM_ShifterType shift_t;
10208
uint32_t shift_n;
10209
10210
switch (encoding) {
10211
case eEncodingT1:
10212
// d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
10213
d = Bits32(opcode, 2, 0);
10214
n = Bits32(opcode, 5, 3);
10215
m = Bits32(opcode, 8, 6);
10216
setflags = !InITBlock();
10217
10218
// (shift_t, shift_n) = (SRType_LSL, 0);
10219
shift_t = SRType_LSL;
10220
shift_n = 0;
10221
10222
break;
10223
10224
case eEncodingT2:
10225
// d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S =="1");
10226
d = Bits32(opcode, 11, 8);
10227
n = Bits32(opcode, 19, 16);
10228
m = Bits32(opcode, 3, 0);
10229
setflags = BitIsSet(opcode, 20);
10230
10231
// if Rd == "1111" && S == "1" then SEE CMP (register);
10232
if (d == 15 && setflags == 1)
10233
return EmulateCMPImm(opcode, eEncodingT3);
10234
10235
// if Rn == "1101" then SEE SUB (SP minus register);
10236
if (n == 13)
10237
return EmulateSUBSPReg(opcode, eEncodingT1);
10238
10239
// (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
10240
shift_n = DecodeImmShiftThumb(opcode, shift_t);
10241
10242
// if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then
10243
// UNPREDICTABLE;
10244
if ((d == 13) || ((d == 15) && BitIsClear(opcode, 20)) || (n == 15) ||
10245
BadReg(m))
10246
return false;
10247
10248
break;
10249
10250
case eEncodingA1:
10251
// if Rn == '1101' then SEE SUB (SP minus register);
10252
// d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
10253
d = Bits32(opcode, 15, 12);
10254
n = Bits32(opcode, 19, 16);
10255
m = Bits32(opcode, 3, 0);
10256
setflags = BitIsSet(opcode, 20);
10257
10258
// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
10259
// instructions;
10260
if ((d == 15) && setflags)
10261
EmulateSUBSPcLrEtc(opcode, encoding);
10262
10263
// (shift_t, shift_n) = DecodeImmShift(type, imm5);
10264
shift_n = DecodeImmShiftARM(opcode, shift_t);
10265
10266
break;
10267
10268
default:
10269
return false;
10270
}
10271
10272
// shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10273
uint32_t Rm = ReadCoreReg(m, &success);
10274
if (!success)
10275
return false;
10276
10277
uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);
10278
if (!success)
10279
return false;
10280
10281
// (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
10282
uint32_t Rn = ReadCoreReg(n, &success);
10283
if (!success)
10284
return false;
10285
10286
AddWithCarryResult res = AddWithCarry(Rn, ~shifted, 1);
10287
10288
// if d == 15 then // Can only occur for ARM encoding ALUWritePC(result);
10289
// // setflags is always FALSE here else
10290
// R[d] = result;
10291
// if setflags then
10292
// APSR.N = result<31>;
10293
// APSR.Z = IsZeroBit(result);
10294
// APSR.C = carry;
10295
// APSR.V = overflow;
10296
10297
EmulateInstruction::Context context;
10298
context.type = eContextArithmetic;
10299
std::optional<RegisterInfo> reg_n =
10300
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
10301
std::optional<RegisterInfo> reg_m =
10302
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
10303
context.SetRegisterRegisterOperands(*reg_n, *reg_m);
10304
10305
if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags,
10306
res.carry_out, res.overflow))
10307
return false;
10308
}
10309
return true;
10310
}
10311
10312
// A8.6.202 STREX
10313
// Store Register Exclusive calculates an address from a base register value
10314
// and an immediate offset, and stores a word from a register to memory if the
10315
// executing processor has exclusive access to the memory addressed.
10316
bool EmulateInstructionARM::EmulateSTREX(const uint32_t opcode,
10317
const ARMEncoding encoding) {
10318
#if 0
10319
if ConditionPassed() then
10320
EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10321
address = R[n] + imm32;
10322
if ExclusiveMonitorsPass(address,4) then
10323
MemA[address,4] = R[t];
10324
R[d] = 0;
10325
else
10326
R[d] = 1;
10327
#endif
10328
10329
bool success = false;
10330
10331
if (ConditionPassed(opcode)) {
10332
uint32_t d;
10333
uint32_t t;
10334
uint32_t n;
10335
uint32_t imm32;
10336
const uint32_t addr_byte_size = GetAddressByteSize();
10337
10338
switch (encoding) {
10339
case eEncodingT1:
10340
// d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 =
10341
// ZeroExtend(imm8:'00',
10342
// 32);
10343
d = Bits32(opcode, 11, 8);
10344
t = Bits32(opcode, 15, 12);
10345
n = Bits32(opcode, 19, 16);
10346
imm32 = Bits32(opcode, 7, 0) << 2;
10347
10348
// if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
10349
if (BadReg(d) || BadReg(t) || (n == 15))
10350
return false;
10351
10352
// if d == n || d == t then UNPREDICTABLE;
10353
if ((d == n) || (d == t))
10354
return false;
10355
10356
break;
10357
10358
case eEncodingA1:
10359
// d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero
10360
// offset
10361
d = Bits32(opcode, 15, 12);
10362
t = Bits32(opcode, 3, 0);
10363
n = Bits32(opcode, 19, 16);
10364
imm32 = 0;
10365
10366
// if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
10367
if ((d == 15) || (t == 15) || (n == 15))
10368
return false;
10369
10370
// if d == n || d == t then UNPREDICTABLE;
10371
if ((d == n) || (d == t))
10372
return false;
10373
10374
break;
10375
10376
default:
10377
return false;
10378
}
10379
10380
// address = R[n] + imm32;
10381
uint32_t Rn = ReadCoreReg(n, &success);
10382
if (!success)
10383
return false;
10384
10385
addr_t address = Rn + imm32;
10386
10387
std::optional<RegisterInfo> base_reg =
10388
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
10389
std::optional<RegisterInfo> data_reg =
10390
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
10391
EmulateInstruction::Context context;
10392
context.type = eContextRegisterStore;
10393
context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, imm32);
10394
10395
// if ExclusiveMonitorsPass(address,4) then if (ExclusiveMonitorsPass
10396
// (address, addr_byte_size)) -- For now, for the sake of emulation, we
10397
// will say this
10398
// always return
10399
// true.
10400
if (true) {
10401
// MemA[address,4] = R[t];
10402
uint32_t Rt =
10403
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
10404
if (!success)
10405
return false;
10406
10407
if (!MemAWrite(context, address, Rt, addr_byte_size))
10408
return false;
10409
10410
// R[d] = 0;
10411
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 0))
10412
return false;
10413
}
10414
#if 0 // unreachable because if true
10415
else
10416
{
10417
// R[d] = 1;
10418
if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
10419
return false;
10420
}
10421
#endif // unreachable because if true
10422
}
10423
return true;
10424
}
10425
10426
// A8.6.197 STRB (immediate, ARM)
10427
bool EmulateInstructionARM::EmulateSTRBImmARM(const uint32_t opcode,
10428
const ARMEncoding encoding) {
10429
#if 0
10430
if ConditionPassed() then
10431
EncodingSpecificOperations();
10432
offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10433
address = if index then offset_addr else R[n];
10434
MemU[address,1] = R[t]<7:0>;
10435
if wback then R[n] = offset_addr;
10436
#endif
10437
10438
bool success = false;
10439
10440
if (ConditionPassed(opcode)) {
10441
uint32_t t;
10442
uint32_t n;
10443
uint32_t imm32;
10444
bool index;
10445
bool add;
10446
bool wback;
10447
10448
switch (encoding) {
10449
case eEncodingA1:
10450
// if P == '0' && W == '1' then SEE STRBT;
10451
// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
10452
t = Bits32(opcode, 15, 12);
10453
n = Bits32(opcode, 19, 16);
10454
imm32 = Bits32(opcode, 11, 0);
10455
10456
// index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10457
index = BitIsSet(opcode, 24);
10458
add = BitIsSet(opcode, 23);
10459
wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10460
10461
// if t == 15 then UNPREDICTABLE;
10462
if (t == 15)
10463
return false;
10464
10465
// if wback && (n == 15 || n == t) then UNPREDICTABLE;
10466
if (wback && ((n == 15) || (n == t)))
10467
return false;
10468
10469
break;
10470
10471
default:
10472
return false;
10473
}
10474
10475
// offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10476
uint32_t Rn = ReadCoreReg(n, &success);
10477
if (!success)
10478
return false;
10479
10480
addr_t offset_addr;
10481
if (add)
10482
offset_addr = Rn + imm32;
10483
else
10484
offset_addr = Rn - imm32;
10485
10486
// address = if index then offset_addr else R[n];
10487
addr_t address;
10488
if (index)
10489
address = offset_addr;
10490
else
10491
address = Rn;
10492
10493
// MemU[address,1] = R[t]<7:0>;
10494
uint32_t Rt = ReadCoreReg(t, &success);
10495
if (!success)
10496
return false;
10497
10498
std::optional<RegisterInfo> base_reg =
10499
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
10500
std::optional<RegisterInfo> data_reg =
10501
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
10502
EmulateInstruction::Context context;
10503
context.type = eContextRegisterStore;
10504
context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);
10505
10506
if (!MemUWrite(context, address, Bits32(Rt, 7, 0), 1))
10507
return false;
10508
10509
// if wback then R[n] = offset_addr;
10510
if (wback) {
10511
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10512
offset_addr))
10513
return false;
10514
}
10515
}
10516
return true;
10517
}
10518
10519
// A8.6.194 STR (immediate, ARM)
10520
bool EmulateInstructionARM::EmulateSTRImmARM(const uint32_t opcode,
10521
const ARMEncoding encoding) {
10522
#if 0
10523
if ConditionPassed() then
10524
EncodingSpecificOperations();
10525
offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10526
address = if index then offset_addr else R[n];
10527
MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
10528
if wback then R[n] = offset_addr;
10529
#endif
10530
10531
bool success = false;
10532
10533
if (ConditionPassed(opcode)) {
10534
uint32_t t;
10535
uint32_t n;
10536
uint32_t imm32;
10537
bool index;
10538
bool add;
10539
bool wback;
10540
10541
const uint32_t addr_byte_size = GetAddressByteSize();
10542
10543
switch (encoding) {
10544
case eEncodingA1:
10545
// if P == '0' && W == '1' then SEE STRT;
10546
// if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 ==
10547
// '000000000100' then SEE PUSH;
10548
// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
10549
t = Bits32(opcode, 15, 12);
10550
n = Bits32(opcode, 19, 16);
10551
imm32 = Bits32(opcode, 11, 0);
10552
10553
// index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10554
index = BitIsSet(opcode, 24);
10555
add = BitIsSet(opcode, 23);
10556
wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10557
10558
// if wback && (n == 15 || n == t) then UNPREDICTABLE;
10559
if (wback && ((n == 15) || (n == t)))
10560
return false;
10561
10562
break;
10563
10564
default:
10565
return false;
10566
}
10567
10568
// offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10569
uint32_t Rn = ReadCoreReg(n, &success);
10570
if (!success)
10571
return false;
10572
10573
addr_t offset_addr;
10574
if (add)
10575
offset_addr = Rn + imm32;
10576
else
10577
offset_addr = Rn - imm32;
10578
10579
// address = if index then offset_addr else R[n];
10580
addr_t address;
10581
if (index)
10582
address = offset_addr;
10583
else
10584
address = Rn;
10585
10586
std::optional<RegisterInfo> base_reg =
10587
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
10588
std::optional<RegisterInfo> data_reg =
10589
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
10590
EmulateInstruction::Context context;
10591
context.type = eContextRegisterStore;
10592
context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);
10593
10594
// MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
10595
uint32_t Rt = ReadCoreReg(t, &success);
10596
if (!success)
10597
return false;
10598
10599
if (t == 15) {
10600
uint32_t pc_value = ReadCoreReg(PC_REG, &success);
10601
if (!success)
10602
return false;
10603
10604
if (!MemUWrite(context, address, pc_value, addr_byte_size))
10605
return false;
10606
} else {
10607
if (!MemUWrite(context, address, Rt, addr_byte_size))
10608
return false;
10609
}
10610
10611
// if wback then R[n] = offset_addr;
10612
if (wback) {
10613
context.type = eContextAdjustBaseRegister;
10614
context.SetImmediate(offset_addr);
10615
10616
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10617
offset_addr))
10618
return false;
10619
}
10620
}
10621
return true;
10622
}
10623
10624
// A8.6.66 LDRD (immediate)
10625
// Load Register Dual (immediate) calculates an address from a base register
10626
// value and an immediate offset, loads two words from memory, and writes them
10627
// to two registers. It can use offset, post-indexed, or pre-indexed
10628
// addressing.
10629
bool EmulateInstructionARM::EmulateLDRDImmediate(const uint32_t opcode,
10630
const ARMEncoding encoding) {
10631
#if 0
10632
if ConditionPassed() then
10633
EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10634
offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10635
address = if index then offset_addr else R[n];
10636
R[t] = MemA[address,4];
10637
R[t2] = MemA[address+4,4];
10638
if wback then R[n] = offset_addr;
10639
#endif
10640
10641
bool success = false;
10642
10643
if (ConditionPassed(opcode)) {
10644
uint32_t t;
10645
uint32_t t2;
10646
uint32_t n;
10647
uint32_t imm32;
10648
bool index;
10649
bool add;
10650
bool wback;
10651
10652
switch (encoding) {
10653
case eEncodingT1:
10654
// if P == '0' && W == '0' then SEE 'Related encodings';
10655
// if Rn == '1111' then SEE LDRD (literal);
10656
// t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 =
10657
// ZeroExtend(imm8:'00', 32);
10658
t = Bits32(opcode, 15, 12);
10659
t2 = Bits32(opcode, 11, 8);
10660
n = Bits32(opcode, 19, 16);
10661
imm32 = Bits32(opcode, 7, 0) << 2;
10662
10663
// index = (P == '1'); add = (U == '1'); wback = (W == '1');
10664
index = BitIsSet(opcode, 24);
10665
add = BitIsSet(opcode, 23);
10666
wback = BitIsSet(opcode, 21);
10667
10668
// if wback && (n == t || n == t2) then UNPREDICTABLE;
10669
if (wback && ((n == t) || (n == t2)))
10670
return false;
10671
10672
// if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
10673
if (BadReg(t) || BadReg(t2) || (t == t2))
10674
return false;
10675
10676
break;
10677
10678
case eEncodingA1:
10679
// if Rn == '1111' then SEE LDRD (literal);
10680
// if Rt<0> == '1' then UNPREDICTABLE;
10681
// t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L,
10682
// 32);
10683
t = Bits32(opcode, 15, 12);
10684
if (BitIsSet(t, 0))
10685
return false;
10686
t2 = t + 1;
10687
n = Bits32(opcode, 19, 16);
10688
imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0);
10689
10690
// index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10691
index = BitIsSet(opcode, 24);
10692
add = BitIsSet(opcode, 23);
10693
wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10694
10695
// if P == '0' && W == '1' then UNPREDICTABLE;
10696
if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
10697
return false;
10698
10699
// if wback && (n == t || n == t2) then UNPREDICTABLE;
10700
if (wback && ((n == t) || (n == t2)))
10701
return false;
10702
10703
// if t2 == 15 then UNPREDICTABLE;
10704
if (t2 == 15)
10705
return false;
10706
10707
break;
10708
10709
default:
10710
return false;
10711
}
10712
10713
// offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10714
uint32_t Rn = ReadCoreReg(n, &success);
10715
if (!success)
10716
return false;
10717
10718
addr_t offset_addr;
10719
if (add)
10720
offset_addr = Rn + imm32;
10721
else
10722
offset_addr = Rn - imm32;
10723
10724
// address = if index then offset_addr else R[n];
10725
addr_t address;
10726
if (index)
10727
address = offset_addr;
10728
else
10729
address = Rn;
10730
10731
// R[t] = MemA[address,4];
10732
10733
EmulateInstruction::Context context;
10734
if (n == 13)
10735
context.type = eContextPopRegisterOffStack;
10736
else
10737
context.type = eContextRegisterLoad;
10738
context.SetAddress(address);
10739
10740
const uint32_t addr_byte_size = GetAddressByteSize();
10741
uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
10742
if (!success)
10743
return false;
10744
10745
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
10746
return false;
10747
10748
// R[t2] = MemA[address+4,4];
10749
context.SetAddress(address + 4);
10750
data = MemARead(context, address + 4, addr_byte_size, 0, &success);
10751
if (!success)
10752
return false;
10753
10754
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2,
10755
data))
10756
return false;
10757
10758
// if wback then R[n] = offset_addr;
10759
if (wback) {
10760
context.type = eContextAdjustBaseRegister;
10761
context.SetAddress(offset_addr);
10762
10763
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10764
offset_addr))
10765
return false;
10766
}
10767
}
10768
return true;
10769
}
10770
10771
// A8.6.68 LDRD (register)
10772
// Load Register Dual (register) calculates an address from a base register
10773
// value and a register offset, loads two words from memory, and writes them to
10774
// two registers. It can use offset, post-indexed or pre-indexed addressing.
10775
bool EmulateInstructionARM::EmulateLDRDRegister(const uint32_t opcode,
10776
const ARMEncoding encoding) {
10777
#if 0
10778
if ConditionPassed() then
10779
EncodingSpecificOperations();
10780
offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10781
address = if index then offset_addr else R[n];
10782
R[t] = MemA[address,4];
10783
R[t2] = MemA[address+4,4];
10784
if wback then R[n] = offset_addr;
10785
#endif
10786
10787
bool success = false;
10788
10789
if (ConditionPassed(opcode)) {
10790
uint32_t t;
10791
uint32_t t2;
10792
uint32_t n;
10793
uint32_t m;
10794
bool index;
10795
bool add;
10796
bool wback;
10797
10798
switch (encoding) {
10799
case eEncodingA1:
10800
// if Rt<0> == '1' then UNPREDICTABLE;
10801
// t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10802
t = Bits32(opcode, 15, 12);
10803
if (BitIsSet(t, 0))
10804
return false;
10805
t2 = t + 1;
10806
n = Bits32(opcode, 19, 16);
10807
m = Bits32(opcode, 3, 0);
10808
10809
// index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10810
index = BitIsSet(opcode, 24);
10811
add = BitIsSet(opcode, 23);
10812
wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10813
10814
// if P == '0' && W == '1' then UNPREDICTABLE;
10815
if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
10816
return false;
10817
10818
// if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10819
if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
10820
return false;
10821
10822
// if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10823
if (wback && ((n == 15) || (n == t) || (n == t2)))
10824
return false;
10825
10826
// if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10827
if ((ArchVersion() < 6) && wback && (m == n))
10828
return false;
10829
break;
10830
10831
default:
10832
return false;
10833
}
10834
10835
uint32_t Rn = ReadCoreReg(n, &success);
10836
if (!success)
10837
return false;
10838
10839
uint32_t Rm = ReadCoreReg(m, &success);
10840
if (!success)
10841
return false;
10842
10843
// offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10844
addr_t offset_addr;
10845
if (add)
10846
offset_addr = Rn + Rm;
10847
else
10848
offset_addr = Rn - Rm;
10849
10850
// address = if index then offset_addr else R[n];
10851
addr_t address;
10852
if (index)
10853
address = offset_addr;
10854
else
10855
address = Rn;
10856
10857
EmulateInstruction::Context context;
10858
if (n == 13)
10859
context.type = eContextPopRegisterOffStack;
10860
else
10861
context.type = eContextRegisterLoad;
10862
context.SetAddress(address);
10863
10864
// R[t] = MemA[address,4];
10865
const uint32_t addr_byte_size = GetAddressByteSize();
10866
uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
10867
if (!success)
10868
return false;
10869
10870
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
10871
return false;
10872
10873
// R[t2] = MemA[address+4,4];
10874
10875
data = MemARead(context, address + 4, addr_byte_size, 0, &success);
10876
if (!success)
10877
return false;
10878
10879
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2,
10880
data))
10881
return false;
10882
10883
// if wback then R[n] = offset_addr;
10884
if (wback) {
10885
context.type = eContextAdjustBaseRegister;
10886
context.SetAddress(offset_addr);
10887
10888
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10889
offset_addr))
10890
return false;
10891
}
10892
}
10893
return true;
10894
}
10895
10896
// A8.6.200 STRD (immediate)
10897
// Store Register Dual (immediate) calculates an address from a base register
10898
// value and an immediate offset, and stores two words from two registers to
10899
// memory. It can use offset, post-indexed, or pre-indexed addressing.
10900
bool EmulateInstructionARM::EmulateSTRDImm(const uint32_t opcode,
10901
const ARMEncoding encoding) {
10902
#if 0
10903
if ConditionPassed() then
10904
EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10905
offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10906
address = if index then offset_addr else R[n];
10907
MemA[address,4] = R[t];
10908
MemA[address+4,4] = R[t2];
10909
if wback then R[n] = offset_addr;
10910
#endif
10911
10912
bool success = false;
10913
10914
if (ConditionPassed(opcode)) {
10915
uint32_t t;
10916
uint32_t t2;
10917
uint32_t n;
10918
uint32_t imm32;
10919
bool index;
10920
bool add;
10921
bool wback;
10922
10923
switch (encoding) {
10924
case eEncodingT1:
10925
// if P == '0' && W == '0' then SEE 'Related encodings';
10926
// t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 =
10927
// ZeroExtend(imm8:'00', 32);
10928
t = Bits32(opcode, 15, 12);
10929
t2 = Bits32(opcode, 11, 8);
10930
n = Bits32(opcode, 19, 16);
10931
imm32 = Bits32(opcode, 7, 0) << 2;
10932
10933
// index = (P == '1'); add = (U == '1'); wback = (W == '1');
10934
index = BitIsSet(opcode, 24);
10935
add = BitIsSet(opcode, 23);
10936
wback = BitIsSet(opcode, 21);
10937
10938
// if wback && (n == t || n == t2) then UNPREDICTABLE;
10939
if (wback && ((n == t) || (n == t2)))
10940
return false;
10941
10942
// if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
10943
if ((n == 15) || BadReg(t) || BadReg(t2))
10944
return false;
10945
10946
break;
10947
10948
case eEncodingA1:
10949
// if Rt<0> == '1' then UNPREDICTABLE;
10950
// t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L,
10951
// 32);
10952
t = Bits32(opcode, 15, 12);
10953
if (BitIsSet(t, 0))
10954
return false;
10955
10956
t2 = t + 1;
10957
n = Bits32(opcode, 19, 16);
10958
imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0);
10959
10960
// index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10961
index = BitIsSet(opcode, 24);
10962
add = BitIsSet(opcode, 23);
10963
wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10964
10965
// if P == '0' && W == '1' then UNPREDICTABLE;
10966
if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
10967
return false;
10968
10969
// if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10970
if (wback && ((n == 15) || (n == t) || (n == t2)))
10971
return false;
10972
10973
// if t2 == 15 then UNPREDICTABLE;
10974
if (t2 == 15)
10975
return false;
10976
10977
break;
10978
10979
default:
10980
return false;
10981
}
10982
10983
std::optional<RegisterInfo> base_reg =
10984
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
10985
10986
uint32_t Rn = ReadCoreReg(n, &success);
10987
if (!success)
10988
return false;
10989
10990
// offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10991
addr_t offset_addr;
10992
if (add)
10993
offset_addr = Rn + imm32;
10994
else
10995
offset_addr = Rn - imm32;
10996
10997
// address = if index then offset_addr else R[n];
10998
addr_t address;
10999
if (index)
11000
address = offset_addr;
11001
else
11002
address = Rn;
11003
11004
// MemA[address,4] = R[t];
11005
std::optional<RegisterInfo> data_reg =
11006
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
11007
11008
uint32_t data = ReadCoreReg(t, &success);
11009
if (!success)
11010
return false;
11011
11012
EmulateInstruction::Context context;
11013
if (n == 13)
11014
context.type = eContextPushRegisterOnStack;
11015
else
11016
context.type = eContextRegisterStore;
11017
context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);
11018
11019
const uint32_t addr_byte_size = GetAddressByteSize();
11020
11021
if (!MemAWrite(context, address, data, addr_byte_size))
11022
return false;
11023
11024
// MemA[address+4,4] = R[t2];
11025
data_reg = GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2);
11026
context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
11027
(address + 4) - Rn);
11028
11029
data = ReadCoreReg(t2, &success);
11030
if (!success)
11031
return false;
11032
11033
if (!MemAWrite(context, address + 4, data, addr_byte_size))
11034
return false;
11035
11036
// if wback then R[n] = offset_addr;
11037
if (wback) {
11038
if (n == 13)
11039
context.type = eContextAdjustStackPointer;
11040
else
11041
context.type = eContextAdjustBaseRegister;
11042
context.SetAddress(offset_addr);
11043
11044
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11045
offset_addr))
11046
return false;
11047
}
11048
}
11049
return true;
11050
}
11051
11052
// A8.6.201 STRD (register)
11053
bool EmulateInstructionARM::EmulateSTRDReg(const uint32_t opcode,
11054
const ARMEncoding encoding) {
11055
#if 0
11056
if ConditionPassed() then
11057
EncodingSpecificOperations();
11058
offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
11059
address = if index then offset_addr else R[n];
11060
MemA[address,4] = R[t];
11061
MemA[address+4,4] = R[t2];
11062
if wback then R[n] = offset_addr;
11063
#endif
11064
11065
bool success = false;
11066
11067
if (ConditionPassed(opcode)) {
11068
uint32_t t;
11069
uint32_t t2;
11070
uint32_t n;
11071
uint32_t m;
11072
bool index;
11073
bool add;
11074
bool wback;
11075
11076
switch (encoding) {
11077
case eEncodingA1:
11078
// if Rt<0> == '1' then UNPREDICTABLE;
11079
// t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
11080
t = Bits32(opcode, 15, 12);
11081
if (BitIsSet(t, 0))
11082
return false;
11083
11084
t2 = t + 1;
11085
n = Bits32(opcode, 19, 16);
11086
m = Bits32(opcode, 3, 0);
11087
11088
// index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
11089
index = BitIsSet(opcode, 24);
11090
add = BitIsSet(opcode, 23);
11091
wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
11092
11093
// if P == '0' && W == '1' then UNPREDICTABLE;
11094
if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
11095
return false;
11096
11097
// if t2 == 15 || m == 15 then UNPREDICTABLE;
11098
if ((t2 == 15) || (m == 15))
11099
return false;
11100
11101
// if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
11102
if (wback && ((n == 15) || (n == t) || (n == t2)))
11103
return false;
11104
11105
// if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
11106
if ((ArchVersion() < 6) && wback && (m == n))
11107
return false;
11108
11109
break;
11110
11111
default:
11112
return false;
11113
}
11114
11115
uint32_t Rn = ReadCoreReg(n, &success);
11116
if (!success)
11117
return false;
11118
11119
uint32_t Rm = ReadCoreReg(m, &success);
11120
if (!success)
11121
return false;
11122
11123
// offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
11124
addr_t offset_addr;
11125
if (add)
11126
offset_addr = Rn + Rm;
11127
else
11128
offset_addr = Rn - Rm;
11129
11130
// address = if index then offset_addr else R[n];
11131
addr_t address;
11132
if (index)
11133
address = offset_addr;
11134
else
11135
address = Rn;
11136
// MemA[address,4] = R[t];
11137
uint32_t Rt = ReadCoreReg(t, &success);
11138
if (!success)
11139
return false;
11140
11141
EmulateInstruction::Context context;
11142
if (t == 13)
11143
context.type = eContextPushRegisterOnStack;
11144
else
11145
context.type = eContextRegisterStore;
11146
11147
std::optional<RegisterInfo> base_reg =
11148
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
11149
std::optional<RegisterInfo> offset_reg =
11150
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
11151
std::optional<RegisterInfo> data_reg =
11152
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
11153
context.SetRegisterToRegisterPlusIndirectOffset(*base_reg, *offset_reg,
11154
*data_reg);
11155
11156
const uint32_t addr_byte_size = GetAddressByteSize();
11157
11158
if (!MemAWrite(context, address, Rt, addr_byte_size))
11159
return false;
11160
11161
// MemA[address+4,4] = R[t2];
11162
uint32_t Rt2 = ReadCoreReg(t2, &success);
11163
if (!success)
11164
return false;
11165
11166
data_reg = GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2);
11167
11168
context.SetRegisterToRegisterPlusIndirectOffset(*base_reg, *offset_reg,
11169
*data_reg);
11170
11171
if (!MemAWrite(context, address + 4, Rt2, addr_byte_size))
11172
return false;
11173
11174
// if wback then R[n] = offset_addr;
11175
if (wback) {
11176
context.type = eContextAdjustBaseRegister;
11177
context.SetAddress(offset_addr);
11178
11179
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11180
offset_addr))
11181
return false;
11182
}
11183
}
11184
return true;
11185
}
11186
11187
// A8.6.319 VLDM
11188
// Vector Load Multiple loads multiple extension registers from consecutive
11189
// memory locations using an address from an ARM core register.
11190
bool EmulateInstructionARM::EmulateVLDM(const uint32_t opcode,
11191
const ARMEncoding encoding) {
11192
#if 0
11193
if ConditionPassed() then
11194
EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11195
address = if add then R[n] else R[n]-imm32;
11196
if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11197
for r = 0 to regs-1
11198
if single_regs then
11199
S[d+r] = MemA[address,4]; address = address+4;
11200
else
11201
word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
11202
// Combine the word-aligned words in the correct order for
11203
// current endianness.
11204
D[d+r] = if BigEndian() then word1:word2 else word2:word1;
11205
#endif
11206
11207
bool success = false;
11208
11209
if (ConditionPassed(opcode)) {
11210
bool single_regs;
11211
bool add;
11212
bool wback;
11213
uint32_t d;
11214
uint32_t n;
11215
uint32_t imm32;
11216
uint32_t regs;
11217
11218
switch (encoding) {
11219
case eEncodingT1:
11220
case eEncodingA1:
11221
// if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11222
// if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;
11223
// if P == '1' && W == '0' then SEE VLDR;
11224
// if P == U && W == '1' then UNDEFINED;
11225
if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11226
return false;
11227
11228
// // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11229
// !), 101 (DB with !)
11230
// single_regs = FALSE; add = (U == '1'); wback = (W == '1');
11231
single_regs = false;
11232
add = BitIsSet(opcode, 23);
11233
wback = BitIsSet(opcode, 21);
11234
11235
// d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
11236
d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11237
n = Bits32(opcode, 19, 16);
11238
imm32 = Bits32(opcode, 7, 0) << 2;
11239
11240
// regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FLDMX'.
11241
regs = Bits32(opcode, 7, 0) / 2;
11242
11243
// if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11244
// UNPREDICTABLE;
11245
if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
11246
return false;
11247
11248
// if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
11249
if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
11250
return false;
11251
11252
break;
11253
11254
case eEncodingT2:
11255
case eEncodingA2:
11256
// if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11257
// if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;
11258
// if P == '1' && W == '0' then SEE VLDR;
11259
// if P == U && W == '1' then UNDEFINED;
11260
if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11261
return false;
11262
11263
// // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11264
// !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W
11265
// == '1'); d =
11266
// UInt(Vd:D); n = UInt(Rn);
11267
single_regs = true;
11268
add = BitIsSet(opcode, 23);
11269
wback = BitIsSet(opcode, 21);
11270
d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11271
n = Bits32(opcode, 19, 16);
11272
11273
// imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
11274
imm32 = Bits32(opcode, 7, 0) << 2;
11275
regs = Bits32(opcode, 7, 0);
11276
11277
// if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11278
// UNPREDICTABLE;
11279
if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11280
return false;
11281
11282
// if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
11283
if ((regs == 0) || ((d + regs) > 32))
11284
return false;
11285
break;
11286
11287
default:
11288
return false;
11289
}
11290
11291
uint32_t Rn = ReadCoreReg(n, &success);
11292
if (!success)
11293
return false;
11294
11295
// address = if add then R[n] else R[n]-imm32;
11296
addr_t address;
11297
if (add)
11298
address = Rn;
11299
else
11300
address = Rn - imm32;
11301
11302
// if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11303
EmulateInstruction::Context context;
11304
11305
if (wback) {
11306
uint32_t value;
11307
if (add)
11308
value = Rn + imm32;
11309
else
11310
value = Rn - imm32;
11311
11312
context.type = eContextAdjustBaseRegister;
11313
context.SetImmediateSigned(value - Rn);
11314
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11315
value))
11316
return false;
11317
}
11318
11319
const uint32_t addr_byte_size = GetAddressByteSize();
11320
uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
11321
11322
context.type = eContextRegisterLoad;
11323
11324
std::optional<RegisterInfo> base_reg =
11325
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
11326
11327
// for r = 0 to regs-1
11328
for (uint32_t r = 0; r < regs; ++r) {
11329
if (single_regs) {
11330
// S[d+r] = MemA[address,4]; address = address+4;
11331
context.SetRegisterPlusOffset(*base_reg, address - Rn);
11332
11333
uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
11334
if (!success)
11335
return false;
11336
11337
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
11338
start_reg + d + r, data))
11339
return false;
11340
11341
address = address + 4;
11342
} else {
11343
// word1 = MemA[address,4]; word2 = MemA[address+4,4]; address =
11344
// address+8;
11345
context.SetRegisterPlusOffset(*base_reg, address - Rn);
11346
uint32_t word1 =
11347
MemARead(context, address, addr_byte_size, 0, &success);
11348
if (!success)
11349
return false;
11350
11351
context.SetRegisterPlusOffset(*base_reg, (address + 4) - Rn);
11352
uint32_t word2 =
11353
MemARead(context, address + 4, addr_byte_size, 0, &success);
11354
if (!success)
11355
return false;
11356
11357
address = address + 8;
11358
// // Combine the word-aligned words in the correct order for current
11359
// endianness.
11360
// D[d+r] = if BigEndian() then word1:word2 else word2:word1;
11361
uint64_t data;
11362
if (GetByteOrder() == eByteOrderBig) {
11363
data = word1;
11364
data = (data << 32) | word2;
11365
} else {
11366
data = word2;
11367
data = (data << 32) | word1;
11368
}
11369
11370
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
11371
start_reg + d + r, data))
11372
return false;
11373
}
11374
}
11375
}
11376
return true;
11377
}
11378
11379
// A8.6.399 VSTM
11380
// Vector Store Multiple stores multiple extension registers to consecutive
11381
// memory locations using an address from an
11382
// ARM core register.
11383
bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode,
11384
const ARMEncoding encoding) {
11385
#if 0
11386
if ConditionPassed() then
11387
EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11388
address = if add then R[n] else R[n]-imm32;
11389
if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11390
for r = 0 to regs-1
11391
if single_regs then
11392
MemA[address,4] = S[d+r]; address = address+4;
11393
else
11394
// Store as two word-aligned words in the correct order for
11395
// current endianness.
11396
MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
11397
MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
11398
address = address+8;
11399
#endif
11400
11401
bool success = false;
11402
11403
if (ConditionPassed(opcode)) {
11404
bool single_regs;
11405
bool add;
11406
bool wback;
11407
uint32_t d;
11408
uint32_t n;
11409
uint32_t imm32;
11410
uint32_t regs;
11411
11412
switch (encoding) {
11413
case eEncodingT1:
11414
case eEncodingA1:
11415
// if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11416
// if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;
11417
// if P == '1' && W == '0' then SEE VSTR;
11418
// if P == U && W == '1' then UNDEFINED;
11419
if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11420
return false;
11421
11422
// // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11423
// !), 101 (DB with !)
11424
// single_regs = FALSE; add = (U == '1'); wback = (W == '1');
11425
single_regs = false;
11426
add = BitIsSet(opcode, 23);
11427
wback = BitIsSet(opcode, 21);
11428
11429
// d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
11430
d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11431
n = Bits32(opcode, 19, 16);
11432
imm32 = Bits32(opcode, 7, 0) << 2;
11433
11434
// regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FSTMX'.
11435
regs = Bits32(opcode, 7, 0) / 2;
11436
11437
// if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11438
// UNPREDICTABLE;
11439
if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11440
return false;
11441
11442
// if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
11443
if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
11444
return false;
11445
11446
break;
11447
11448
case eEncodingT2:
11449
case eEncodingA2:
11450
// if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11451
// if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;
11452
// if P == '1' && W == '0' then SEE VSTR;
11453
// if P == U && W == '1' then UNDEFINED;
11454
if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11455
return false;
11456
11457
// // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11458
// !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W
11459
// == '1'); d =
11460
// UInt(Vd:D); n = UInt(Rn);
11461
single_regs = true;
11462
add = BitIsSet(opcode, 23);
11463
wback = BitIsSet(opcode, 21);
11464
d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11465
n = Bits32(opcode, 19, 16);
11466
11467
// imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
11468
imm32 = Bits32(opcode, 7, 0) << 2;
11469
regs = Bits32(opcode, 7, 0);
11470
11471
// if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11472
// UNPREDICTABLE;
11473
if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11474
return false;
11475
11476
// if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
11477
if ((regs == 0) || ((d + regs) > 32))
11478
return false;
11479
11480
break;
11481
11482
default:
11483
return false;
11484
}
11485
11486
std::optional<RegisterInfo> base_reg =
11487
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
11488
11489
uint32_t Rn = ReadCoreReg(n, &success);
11490
if (!success)
11491
return false;
11492
11493
// address = if add then R[n] else R[n]-imm32;
11494
addr_t address;
11495
if (add)
11496
address = Rn;
11497
else
11498
address = Rn - imm32;
11499
11500
EmulateInstruction::Context context;
11501
// if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11502
if (wback) {
11503
uint32_t value;
11504
if (add)
11505
value = Rn + imm32;
11506
else
11507
value = Rn - imm32;
11508
11509
context.type = eContextAdjustBaseRegister;
11510
context.SetRegisterPlusOffset(*base_reg, value - Rn);
11511
11512
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11513
value))
11514
return false;
11515
}
11516
11517
const uint32_t addr_byte_size = GetAddressByteSize();
11518
uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
11519
11520
context.type = eContextRegisterStore;
11521
// for r = 0 to regs-1
11522
for (uint32_t r = 0; r < regs; ++r) {
11523
11524
if (single_regs) {
11525
// MemA[address,4] = S[d+r]; address = address+4;
11526
uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF,
11527
start_reg + d + r, 0, &success);
11528
if (!success)
11529
return false;
11530
11531
std::optional<RegisterInfo> data_reg =
11532
GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r);
11533
context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
11534
address - Rn);
11535
if (!MemAWrite(context, address, data, addr_byte_size))
11536
return false;
11537
11538
address = address + 4;
11539
} else {
11540
// // Store as two word-aligned words in the correct order for current
11541
// endianness. MemA[address,4] = if BigEndian() then D[d+r]<63:32> else
11542
// D[d+r]<31:0>;
11543
// MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else
11544
// D[d+r]<63:32>;
11545
uint64_t data = ReadRegisterUnsigned(eRegisterKindDWARF,
11546
start_reg + d + r, 0, &success);
11547
if (!success)
11548
return false;
11549
11550
std::optional<RegisterInfo> data_reg =
11551
GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r);
11552
11553
if (GetByteOrder() == eByteOrderBig) {
11554
context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
11555
address - Rn);
11556
if (!MemAWrite(context, address, Bits64(data, 63, 32),
11557
addr_byte_size))
11558
return false;
11559
11560
context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
11561
(address + 4) - Rn);
11562
if (!MemAWrite(context, address + 4, Bits64(data, 31, 0),
11563
addr_byte_size))
11564
return false;
11565
} else {
11566
context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
11567
address - Rn);
11568
if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size))
11569
return false;
11570
11571
context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
11572
(address + 4) - Rn);
11573
if (!MemAWrite(context, address + 4, Bits64(data, 63, 32),
11574
addr_byte_size))
11575
return false;
11576
}
11577
// address = address+8;
11578
address = address + 8;
11579
}
11580
}
11581
}
11582
return true;
11583
}
11584
11585
// A8.6.320
11586
// This instruction loads a single extension register from memory, using an
11587
// address from an ARM core register, with an optional offset.
11588
bool EmulateInstructionARM::EmulateVLDR(const uint32_t opcode,
11589
ARMEncoding encoding) {
11590
#if 0
11591
if ConditionPassed() then
11592
EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11593
base = if n == 15 then Align(PC,4) else R[n];
11594
address = if add then (base + imm32) else (base - imm32);
11595
if single_reg then
11596
S[d] = MemA[address,4];
11597
else
11598
word1 = MemA[address,4]; word2 = MemA[address+4,4];
11599
// Combine the word-aligned words in the correct order for current
11600
// endianness.
11601
D[d] = if BigEndian() then word1:word2 else word2:word1;
11602
#endif
11603
11604
bool success = false;
11605
11606
if (ConditionPassed(opcode)) {
11607
bool single_reg;
11608
bool add;
11609
uint32_t imm32;
11610
uint32_t d;
11611
uint32_t n;
11612
11613
switch (encoding) {
11614
case eEncodingT1:
11615
case eEncodingA1:
11616
// single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00',
11617
// 32);
11618
single_reg = false;
11619
add = BitIsSet(opcode, 23);
11620
imm32 = Bits32(opcode, 7, 0) << 2;
11621
11622
// d = UInt(D:Vd); n = UInt(Rn);
11623
d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11624
n = Bits32(opcode, 19, 16);
11625
11626
break;
11627
11628
case eEncodingT2:
11629
case eEncodingA2:
11630
// single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
11631
single_reg = true;
11632
add = BitIsSet(opcode, 23);
11633
imm32 = Bits32(opcode, 7, 0) << 2;
11634
11635
// d = UInt(Vd:D); n = UInt(Rn);
11636
d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11637
n = Bits32(opcode, 19, 16);
11638
11639
break;
11640
11641
default:
11642
return false;
11643
}
11644
std::optional<RegisterInfo> base_reg =
11645
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
11646
11647
uint32_t Rn = ReadCoreReg(n, &success);
11648
if (!success)
11649
return false;
11650
11651
// base = if n == 15 then Align(PC,4) else R[n];
11652
uint32_t base;
11653
if (n == 15)
11654
base = AlignPC(Rn);
11655
else
11656
base = Rn;
11657
11658
// address = if add then (base + imm32) else (base - imm32);
11659
addr_t address;
11660
if (add)
11661
address = base + imm32;
11662
else
11663
address = base - imm32;
11664
11665
const uint32_t addr_byte_size = GetAddressByteSize();
11666
uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11667
11668
EmulateInstruction::Context context;
11669
context.type = eContextRegisterLoad;
11670
context.SetRegisterPlusOffset(*base_reg, address - base);
11671
11672
if (single_reg) {
11673
// S[d] = MemA[address,4];
11674
uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
11675
if (!success)
11676
return false;
11677
11678
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d,
11679
data))
11680
return false;
11681
} else {
11682
// word1 = MemA[address,4]; word2 = MemA[address+4,4];
11683
uint32_t word1 = MemARead(context, address, addr_byte_size, 0, &success);
11684
if (!success)
11685
return false;
11686
11687
context.SetRegisterPlusOffset(*base_reg, (address + 4) - base);
11688
uint32_t word2 =
11689
MemARead(context, address + 4, addr_byte_size, 0, &success);
11690
if (!success)
11691
return false;
11692
// // Combine the word-aligned words in the correct order for current
11693
// endianness.
11694
// D[d] = if BigEndian() then word1:word2 else word2:word1;
11695
uint64_t data64;
11696
if (GetByteOrder() == eByteOrderBig) {
11697
data64 = word1;
11698
data64 = (data64 << 32) | word2;
11699
} else {
11700
data64 = word2;
11701
data64 = (data64 << 32) | word1;
11702
}
11703
11704
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d,
11705
data64))
11706
return false;
11707
}
11708
}
11709
return true;
11710
}
11711
11712
// A8.6.400 VSTR
11713
// This instruction stores a signle extension register to memory, using an
11714
// address from an ARM core register, with an optional offset.
11715
bool EmulateInstructionARM::EmulateVSTR(const uint32_t opcode,
11716
ARMEncoding encoding) {
11717
#if 0
11718
if ConditionPassed() then
11719
EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11720
address = if add then (R[n] + imm32) else (R[n] - imm32);
11721
if single_reg then
11722
MemA[address,4] = S[d];
11723
else
11724
// Store as two word-aligned words in the correct order for current
11725
// endianness.
11726
MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11727
MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11728
#endif
11729
11730
bool success = false;
11731
11732
if (ConditionPassed(opcode)) {
11733
bool single_reg;
11734
bool add;
11735
uint32_t imm32;
11736
uint32_t d;
11737
uint32_t n;
11738
11739
switch (encoding) {
11740
case eEncodingT1:
11741
case eEncodingA1:
11742
// single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00',
11743
// 32);
11744
single_reg = false;
11745
add = BitIsSet(opcode, 23);
11746
imm32 = Bits32(opcode, 7, 0) << 2;
11747
11748
// d = UInt(D:Vd); n = UInt(Rn);
11749
d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11750
n = Bits32(opcode, 19, 16);
11751
11752
// if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11753
if ((n == 15) && (CurrentInstrSet() != eModeARM))
11754
return false;
11755
11756
break;
11757
11758
case eEncodingT2:
11759
case eEncodingA2:
11760
// single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
11761
single_reg = true;
11762
add = BitIsSet(opcode, 23);
11763
imm32 = Bits32(opcode, 7, 0) << 2;
11764
11765
// d = UInt(Vd:D); n = UInt(Rn);
11766
d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11767
n = Bits32(opcode, 19, 16);
11768
11769
// if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11770
if ((n == 15) && (CurrentInstrSet() != eModeARM))
11771
return false;
11772
11773
break;
11774
11775
default:
11776
return false;
11777
}
11778
11779
uint32_t Rn = ReadCoreReg(n, &success);
11780
if (!success)
11781
return false;
11782
11783
// address = if add then (R[n] + imm32) else (R[n] - imm32);
11784
addr_t address;
11785
if (add)
11786
address = Rn + imm32;
11787
else
11788
address = Rn - imm32;
11789
11790
const uint32_t addr_byte_size = GetAddressByteSize();
11791
uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11792
11793
std::optional<RegisterInfo> base_reg =
11794
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
11795
std::optional<RegisterInfo> data_reg =
11796
GetRegisterInfo(eRegisterKindDWARF, start_reg + d);
11797
EmulateInstruction::Context context;
11798
context.type = eContextRegisterStore;
11799
context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);
11800
11801
if (single_reg) {
11802
// MemA[address,4] = S[d];
11803
uint32_t data =
11804
ReadRegisterUnsigned(eRegisterKindDWARF, start_reg + d, 0, &success);
11805
if (!success)
11806
return false;
11807
11808
if (!MemAWrite(context, address, data, addr_byte_size))
11809
return false;
11810
} else {
11811
// // Store as two word-aligned words in the correct order for current
11812
// endianness.
11813
// MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11814
// MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11815
uint64_t data =
11816
ReadRegisterUnsigned(eRegisterKindDWARF, start_reg + d, 0, &success);
11817
if (!success)
11818
return false;
11819
11820
if (GetByteOrder() == eByteOrderBig) {
11821
if (!MemAWrite(context, address, Bits64(data, 63, 32), addr_byte_size))
11822
return false;
11823
11824
context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
11825
(address + 4) - Rn);
11826
if (!MemAWrite(context, address + 4, Bits64(data, 31, 0),
11827
addr_byte_size))
11828
return false;
11829
} else {
11830
if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size))
11831
return false;
11832
11833
context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
11834
(address + 4) - Rn);
11835
if (!MemAWrite(context, address + 4, Bits64(data, 63, 32),
11836
addr_byte_size))
11837
return false;
11838
}
11839
}
11840
}
11841
return true;
11842
}
11843
11844
// A8.6.307 VLDI1 (multiple single elements) This instruction loads elements
11845
// from memory into one, two, three or four registers, without de-interleaving.
11846
// Every element of each register is loaded.
11847
bool EmulateInstructionARM::EmulateVLD1Multiple(const uint32_t opcode,
11848
ARMEncoding encoding) {
11849
#if 0
11850
if ConditionPassed() then
11851
EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11852
address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11853
if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11854
for r = 0 to regs-1
11855
for e = 0 to elements-1
11856
Elem[D[d+r],e,esize] = MemU[address,ebytes];
11857
address = address + ebytes;
11858
#endif
11859
11860
bool success = false;
11861
11862
if (ConditionPassed(opcode)) {
11863
uint32_t regs;
11864
uint32_t alignment;
11865
uint32_t ebytes;
11866
uint32_t esize;
11867
uint32_t elements;
11868
uint32_t d;
11869
uint32_t n;
11870
uint32_t m;
11871
bool wback;
11872
bool register_index;
11873
11874
switch (encoding) {
11875
case eEncodingT1:
11876
case eEncodingA1: {
11877
// case type of
11878
// when '0111'
11879
// regs = 1; if align<1> == '1' then UNDEFINED;
11880
// when '1010'
11881
// regs = 2; if align == '11' then UNDEFINED;
11882
// when '0110'
11883
// regs = 3; if align<1> == '1' then UNDEFINED;
11884
// when '0010'
11885
// regs = 4;
11886
// otherwise
11887
// SEE 'Related encodings';
11888
uint32_t type = Bits32(opcode, 11, 8);
11889
uint32_t align = Bits32(opcode, 5, 4);
11890
if (type == 7) // '0111'
11891
{
11892
regs = 1;
11893
if (BitIsSet(align, 1))
11894
return false;
11895
} else if (type == 10) // '1010'
11896
{
11897
regs = 2;
11898
if (align == 3)
11899
return false;
11900
11901
} else if (type == 6) // '0110'
11902
{
11903
regs = 3;
11904
if (BitIsSet(align, 1))
11905
return false;
11906
} else if (type == 2) // '0010'
11907
{
11908
regs = 4;
11909
} else
11910
return false;
11911
11912
// alignment = if align == '00' then 1 else 4 << UInt(align);
11913
if (align == 0)
11914
alignment = 1;
11915
else
11916
alignment = 4 << align;
11917
11918
// ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11919
ebytes = 1 << Bits32(opcode, 7, 6);
11920
esize = 8 * ebytes;
11921
elements = 8 / ebytes;
11922
11923
// d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11924
d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11925
n = Bits32(opcode, 19, 15);
11926
m = Bits32(opcode, 3, 0);
11927
11928
// wback = (m != 15); register_index = (m != 15 && m != 13);
11929
wback = (m != 15);
11930
register_index = ((m != 15) && (m != 13));
11931
11932
// if d+regs > 32 then UNPREDICTABLE;
11933
if ((d + regs) > 32)
11934
return false;
11935
} break;
11936
11937
default:
11938
return false;
11939
}
11940
11941
std::optional<RegisterInfo> base_reg =
11942
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
11943
11944
uint32_t Rn = ReadCoreReg(n, &success);
11945
if (!success)
11946
return false;
11947
11948
// address = R[n]; if (address MOD alignment) != 0 then
11949
// GenerateAlignmentException();
11950
addr_t address = Rn;
11951
if ((address % alignment) != 0)
11952
return false;
11953
11954
EmulateInstruction::Context context;
11955
// if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11956
if (wback) {
11957
uint32_t Rm = ReadCoreReg(m, &success);
11958
if (!success)
11959
return false;
11960
11961
uint32_t offset;
11962
if (register_index)
11963
offset = Rm;
11964
else
11965
offset = 8 * regs;
11966
11967
uint32_t value = Rn + offset;
11968
context.type = eContextAdjustBaseRegister;
11969
context.SetRegisterPlusOffset(*base_reg, offset);
11970
11971
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11972
value))
11973
return false;
11974
}
11975
11976
// for r = 0 to regs-1
11977
for (uint32_t r = 0; r < regs; ++r) {
11978
// for e = 0 to elements-1
11979
uint64_t assembled_data = 0;
11980
for (uint32_t e = 0; e < elements; ++e) {
11981
// Elem[D[d+r],e,esize] = MemU[address,ebytes];
11982
context.type = eContextRegisterLoad;
11983
context.SetRegisterPlusOffset(*base_reg, address - Rn);
11984
uint64_t data = MemURead(context, address, ebytes, 0, &success);
11985
if (!success)
11986
return false;
11987
11988
assembled_data =
11989
(data << (e * esize)) |
11990
assembled_data; // New data goes to the left of existing data
11991
11992
// address = address + ebytes;
11993
address = address + ebytes;
11994
}
11995
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_d0 + d + r,
11996
assembled_data))
11997
return false;
11998
}
11999
}
12000
return true;
12001
}
12002
12003
// A8.6.308 VLD1 (single element to one lane)
12004
//
12005
bool EmulateInstructionARM::EmulateVLD1Single(const uint32_t opcode,
12006
const ARMEncoding encoding) {
12007
#if 0
12008
if ConditionPassed() then
12009
EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12010
address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12011
if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12012
Elem[D[d],index,esize] = MemU[address,ebytes];
12013
#endif
12014
12015
bool success = false;
12016
12017
if (ConditionPassed(opcode)) {
12018
uint32_t ebytes;
12019
uint32_t esize;
12020
uint32_t index;
12021
uint32_t alignment;
12022
uint32_t d;
12023
uint32_t n;
12024
uint32_t m;
12025
bool wback;
12026
bool register_index;
12027
12028
switch (encoding) {
12029
case eEncodingT1:
12030
case eEncodingA1: {
12031
uint32_t size = Bits32(opcode, 11, 10);
12032
uint32_t index_align = Bits32(opcode, 7, 4);
12033
// if size == '11' then SEE VLD1 (single element to all lanes);
12034
if (size == 3)
12035
return EmulateVLD1SingleAll(opcode, encoding);
12036
// case size of
12037
if (size == 0) // when '00'
12038
{
12039
// if index_align<0> != '0' then UNDEFINED;
12040
if (BitIsClear(index_align, 0))
12041
return false;
12042
12043
// ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
12044
ebytes = 1;
12045
esize = 8;
12046
index = Bits32(index_align, 3, 1);
12047
alignment = 1;
12048
} else if (size == 1) // when '01'
12049
{
12050
// if index_align<1> != '0' then UNDEFINED;
12051
if (BitIsClear(index_align, 1))
12052
return false;
12053
12054
// ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
12055
ebytes = 2;
12056
esize = 16;
12057
index = Bits32(index_align, 3, 2);
12058
12059
// alignment = if index_align<0> == '0' then 1 else 2;
12060
if (BitIsClear(index_align, 0))
12061
alignment = 1;
12062
else
12063
alignment = 2;
12064
} else if (size == 2) // when '10'
12065
{
12066
// if index_align<2> != '0' then UNDEFINED;
12067
if (BitIsClear(index_align, 2))
12068
return false;
12069
12070
// if index_align<1:0> != '00' && index_align<1:0> != '11' then
12071
// UNDEFINED;
12072
if ((Bits32(index_align, 1, 0) != 0) &&
12073
(Bits32(index_align, 1, 0) != 3))
12074
return false;
12075
12076
// ebytes = 4; esize = 32; index = UInt(index_align<3>);
12077
ebytes = 4;
12078
esize = 32;
12079
index = Bit32(index_align, 3);
12080
12081
// alignment = if index_align<1:0> == '00' then 1 else 4;
12082
if (Bits32(index_align, 1, 0) == 0)
12083
alignment = 1;
12084
else
12085
alignment = 4;
12086
} else {
12087
return false;
12088
}
12089
// d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12090
d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12091
n = Bits32(opcode, 19, 16);
12092
m = Bits32(opcode, 3, 0);
12093
12094
// wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15
12095
// then UNPREDICTABLE;
12096
wback = (m != 15);
12097
register_index = ((m != 15) && (m != 13));
12098
12099
if (n == 15)
12100
return false;
12101
12102
} break;
12103
12104
default:
12105
return false;
12106
}
12107
12108
uint32_t Rn = ReadCoreReg(n, &success);
12109
if (!success)
12110
return false;
12111
12112
// address = R[n]; if (address MOD alignment) != 0 then
12113
// GenerateAlignmentException();
12114
addr_t address = Rn;
12115
if ((address % alignment) != 0)
12116
return false;
12117
12118
EmulateInstruction::Context context;
12119
// if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12120
if (wback) {
12121
uint32_t Rm = ReadCoreReg(m, &success);
12122
if (!success)
12123
return false;
12124
12125
uint32_t offset;
12126
if (register_index)
12127
offset = Rm;
12128
else
12129
offset = ebytes;
12130
12131
uint32_t value = Rn + offset;
12132
12133
context.type = eContextAdjustBaseRegister;
12134
std::optional<RegisterInfo> base_reg =
12135
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
12136
context.SetRegisterPlusOffset(*base_reg, offset);
12137
12138
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12139
value))
12140
return false;
12141
}
12142
12143
// Elem[D[d],index,esize] = MemU[address,ebytes];
12144
uint32_t element = MemURead(context, address, esize, 0, &success);
12145
if (!success)
12146
return false;
12147
12148
element = element << (index * esize);
12149
12150
uint64_t reg_data =
12151
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
12152
if (!success)
12153
return false;
12154
12155
uint64_t all_ones = -1;
12156
uint64_t mask = all_ones
12157
<< ((index + 1) * esize); // mask is all 1's to left of
12158
// where 'element' goes, & all 0's
12159
// at element & to the right of element.
12160
if (index > 0)
12161
mask = mask | Bits64(all_ones, (index * esize) - 1,
12162
0); // add 1's to the right of where 'element' goes.
12163
// now mask should be 0's where element goes & 1's everywhere else.
12164
12165
uint64_t masked_reg =
12166
reg_data & mask; // Take original reg value & zero out 'element' bits
12167
reg_data =
12168
masked_reg & element; // Put 'element' into those bits in reg_data.
12169
12170
context.type = eContextRegisterLoad;
12171
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
12172
reg_data))
12173
return false;
12174
}
12175
return true;
12176
}
12177
12178
// A8.6.391 VST1 (multiple single elements) Vector Store (multiple single
12179
// elements) stores elements to memory from one, two, three, or four registers,
12180
// without interleaving. Every element of each register is stored.
12181
bool EmulateInstructionARM::EmulateVST1Multiple(const uint32_t opcode,
12182
ARMEncoding encoding) {
12183
#if 0
12184
if ConditionPassed() then
12185
EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12186
address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12187
if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
12188
for r = 0 to regs-1
12189
for e = 0 to elements-1
12190
MemU[address,ebytes] = Elem[D[d+r],e,esize];
12191
address = address + ebytes;
12192
#endif
12193
12194
bool success = false;
12195
12196
if (ConditionPassed(opcode)) {
12197
uint32_t regs;
12198
uint32_t alignment;
12199
uint32_t ebytes;
12200
uint32_t esize;
12201
uint32_t elements;
12202
uint32_t d;
12203
uint32_t n;
12204
uint32_t m;
12205
bool wback;
12206
bool register_index;
12207
12208
switch (encoding) {
12209
case eEncodingT1:
12210
case eEncodingA1: {
12211
uint32_t type = Bits32(opcode, 11, 8);
12212
uint32_t align = Bits32(opcode, 5, 4);
12213
12214
// case type of
12215
if (type == 7) // when '0111'
12216
{
12217
// regs = 1; if align<1> == '1' then UNDEFINED;
12218
regs = 1;
12219
if (BitIsSet(align, 1))
12220
return false;
12221
} else if (type == 10) // when '1010'
12222
{
12223
// regs = 2; if align == '11' then UNDEFINED;
12224
regs = 2;
12225
if (align == 3)
12226
return false;
12227
} else if (type == 6) // when '0110'
12228
{
12229
// regs = 3; if align<1> == '1' then UNDEFINED;
12230
regs = 3;
12231
if (BitIsSet(align, 1))
12232
return false;
12233
} else if (type == 2) // when '0010'
12234
// regs = 4;
12235
regs = 4;
12236
else // otherwise
12237
// SEE 'Related encodings';
12238
return false;
12239
12240
// alignment = if align == '00' then 1 else 4 << UInt(align);
12241
if (align == 0)
12242
alignment = 1;
12243
else
12244
alignment = 4 << align;
12245
12246
// ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
12247
ebytes = 1 << Bits32(opcode, 7, 6);
12248
esize = 8 * ebytes;
12249
elements = 8 / ebytes;
12250
12251
// d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12252
d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12253
n = Bits32(opcode, 19, 16);
12254
m = Bits32(opcode, 3, 0);
12255
12256
// wback = (m != 15); register_index = (m != 15 && m != 13);
12257
wback = (m != 15);
12258
register_index = ((m != 15) && (m != 13));
12259
12260
// if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
12261
if ((d + regs) > 32)
12262
return false;
12263
12264
if (n == 15)
12265
return false;
12266
12267
} break;
12268
12269
default:
12270
return false;
12271
}
12272
12273
std::optional<RegisterInfo> base_reg =
12274
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
12275
12276
uint32_t Rn = ReadCoreReg(n, &success);
12277
if (!success)
12278
return false;
12279
12280
// address = R[n]; if (address MOD alignment) != 0 then
12281
// GenerateAlignmentException();
12282
addr_t address = Rn;
12283
if ((address % alignment) != 0)
12284
return false;
12285
12286
EmulateInstruction::Context context;
12287
// if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
12288
if (wback) {
12289
uint32_t Rm = ReadCoreReg(m, &success);
12290
if (!success)
12291
return false;
12292
12293
uint32_t offset;
12294
if (register_index)
12295
offset = Rm;
12296
else
12297
offset = 8 * regs;
12298
12299
context.type = eContextAdjustBaseRegister;
12300
context.SetRegisterPlusOffset(*base_reg, offset);
12301
12302
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12303
Rn + offset))
12304
return false;
12305
}
12306
12307
context.type = eContextRegisterStore;
12308
// for r = 0 to regs-1
12309
for (uint32_t r = 0; r < regs; ++r) {
12310
std::optional<RegisterInfo> data_reg =
12311
GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d + r);
12312
uint64_t register_data = ReadRegisterUnsigned(
12313
eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);
12314
if (!success)
12315
return false;
12316
12317
// for e = 0 to elements-1
12318
for (uint32_t e = 0; e < elements; ++e) {
12319
// MemU[address,ebytes] = Elem[D[d+r],e,esize];
12320
uint64_t word = Bits64(register_data, ((e + 1) * esize) - 1, e * esize);
12321
12322
context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
12323
address - Rn);
12324
if (!MemUWrite(context, address, word, ebytes))
12325
return false;
12326
12327
// address = address + ebytes;
12328
address = address + ebytes;
12329
}
12330
}
12331
}
12332
return true;
12333
}
12334
12335
// A8.6.392 VST1 (single element from one lane) This instruction stores one
12336
// element to memory from one element of a register.
12337
bool EmulateInstructionARM::EmulateVST1Single(const uint32_t opcode,
12338
ARMEncoding encoding) {
12339
#if 0
12340
if ConditionPassed() then
12341
EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12342
address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12343
if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12344
MemU[address,ebytes] = Elem[D[d],index,esize];
12345
#endif
12346
12347
bool success = false;
12348
12349
if (ConditionPassed(opcode)) {
12350
uint32_t ebytes;
12351
uint32_t esize;
12352
uint32_t index;
12353
uint32_t alignment;
12354
uint32_t d;
12355
uint32_t n;
12356
uint32_t m;
12357
bool wback;
12358
bool register_index;
12359
12360
switch (encoding) {
12361
case eEncodingT1:
12362
case eEncodingA1: {
12363
uint32_t size = Bits32(opcode, 11, 10);
12364
uint32_t index_align = Bits32(opcode, 7, 4);
12365
12366
// if size == '11' then UNDEFINED;
12367
if (size == 3)
12368
return false;
12369
12370
// case size of
12371
if (size == 0) // when '00'
12372
{
12373
// if index_align<0> != '0' then UNDEFINED;
12374
if (BitIsClear(index_align, 0))
12375
return false;
12376
// ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
12377
ebytes = 1;
12378
esize = 8;
12379
index = Bits32(index_align, 3, 1);
12380
alignment = 1;
12381
} else if (size == 1) // when '01'
12382
{
12383
// if index_align<1> != '0' then UNDEFINED;
12384
if (BitIsClear(index_align, 1))
12385
return false;
12386
12387
// ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
12388
ebytes = 2;
12389
esize = 16;
12390
index = Bits32(index_align, 3, 2);
12391
12392
// alignment = if index_align<0> == '0' then 1 else 2;
12393
if (BitIsClear(index_align, 0))
12394
alignment = 1;
12395
else
12396
alignment = 2;
12397
} else if (size == 2) // when '10'
12398
{
12399
// if index_align<2> != '0' then UNDEFINED;
12400
if (BitIsClear(index_align, 2))
12401
return false;
12402
12403
// if index_align<1:0> != '00' && index_align<1:0> != '11' then
12404
// UNDEFINED;
12405
if ((Bits32(index_align, 1, 0) != 0) &&
12406
(Bits32(index_align, 1, 0) != 3))
12407
return false;
12408
12409
// ebytes = 4; esize = 32; index = UInt(index_align<3>);
12410
ebytes = 4;
12411
esize = 32;
12412
index = Bit32(index_align, 3);
12413
12414
// alignment = if index_align<1:0> == '00' then 1 else 4;
12415
if (Bits32(index_align, 1, 0) == 0)
12416
alignment = 1;
12417
else
12418
alignment = 4;
12419
} else {
12420
return false;
12421
}
12422
// d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12423
d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12424
n = Bits32(opcode, 19, 16);
12425
m = Bits32(opcode, 3, 0);
12426
12427
// wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15
12428
// then UNPREDICTABLE;
12429
wback = (m != 15);
12430
register_index = ((m != 15) && (m != 13));
12431
12432
if (n == 15)
12433
return false;
12434
} break;
12435
12436
default:
12437
return false;
12438
}
12439
12440
std::optional<RegisterInfo> base_reg =
12441
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
12442
12443
uint32_t Rn = ReadCoreReg(n, &success);
12444
if (!success)
12445
return false;
12446
12447
// address = R[n]; if (address MOD alignment) != 0 then
12448
// GenerateAlignmentException();
12449
addr_t address = Rn;
12450
if ((address % alignment) != 0)
12451
return false;
12452
12453
EmulateInstruction::Context context;
12454
// if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12455
if (wback) {
12456
uint32_t Rm = ReadCoreReg(m, &success);
12457
if (!success)
12458
return false;
12459
12460
uint32_t offset;
12461
if (register_index)
12462
offset = Rm;
12463
else
12464
offset = ebytes;
12465
12466
context.type = eContextAdjustBaseRegister;
12467
context.SetRegisterPlusOffset(*base_reg, offset);
12468
12469
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12470
Rn + offset))
12471
return false;
12472
}
12473
12474
// MemU[address,ebytes] = Elem[D[d],index,esize];
12475
uint64_t register_data =
12476
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
12477
if (!success)
12478
return false;
12479
12480
uint64_t word =
12481
Bits64(register_data, ((index + 1) * esize) - 1, index * esize);
12482
12483
std::optional<RegisterInfo> data_reg =
12484
GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d);
12485
context.type = eContextRegisterStore;
12486
context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);
12487
12488
if (!MemUWrite(context, address, word, ebytes))
12489
return false;
12490
}
12491
return true;
12492
}
12493
12494
// A8.6.309 VLD1 (single element to all lanes) This instruction loads one
12495
// element from memory into every element of one or two vectors.
12496
bool EmulateInstructionARM::EmulateVLD1SingleAll(const uint32_t opcode,
12497
const ARMEncoding encoding) {
12498
#if 0
12499
if ConditionPassed() then
12500
EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12501
address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12502
if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12503
replicated_element = Replicate(MemU[address,ebytes], elements);
12504
for r = 0 to regs-1
12505
D[d+r] = replicated_element;
12506
#endif
12507
12508
bool success = false;
12509
12510
if (ConditionPassed(opcode)) {
12511
uint32_t ebytes;
12512
uint32_t elements;
12513
uint32_t regs;
12514
uint32_t alignment;
12515
uint32_t d;
12516
uint32_t n;
12517
uint32_t m;
12518
bool wback;
12519
bool register_index;
12520
12521
switch (encoding) {
12522
case eEncodingT1:
12523
case eEncodingA1: {
12524
// if size == '11' || (size == '00' && a == '1') then UNDEFINED;
12525
uint32_t size = Bits32(opcode, 7, 6);
12526
if ((size == 3) || ((size == 0) && BitIsSet(opcode, 4)))
12527
return false;
12528
12529
// ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == '0'
12530
// then 1 else 2;
12531
ebytes = 1 << size;
12532
elements = 8 / ebytes;
12533
if (BitIsClear(opcode, 5))
12534
regs = 1;
12535
else
12536
regs = 2;
12537
12538
// alignment = if a == '0' then 1 else ebytes;
12539
if (BitIsClear(opcode, 4))
12540
alignment = 1;
12541
else
12542
alignment = ebytes;
12543
12544
// d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12545
d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12546
n = Bits32(opcode, 19, 16);
12547
m = Bits32(opcode, 3, 0);
12548
12549
// wback = (m != 15); register_index = (m != 15 && m != 13);
12550
wback = (m != 15);
12551
register_index = ((m != 15) && (m != 13));
12552
12553
// if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
12554
if ((d + regs) > 32)
12555
return false;
12556
12557
if (n == 15)
12558
return false;
12559
} break;
12560
12561
default:
12562
return false;
12563
}
12564
12565
uint32_t Rn = ReadCoreReg(n, &success);
12566
if (!success)
12567
return false;
12568
12569
// address = R[n]; if (address MOD alignment) != 0 then
12570
// GenerateAlignmentException();
12571
addr_t address = Rn;
12572
if ((address % alignment) != 0)
12573
return false;
12574
12575
EmulateInstruction::Context context;
12576
// if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12577
if (wback) {
12578
uint32_t Rm = ReadCoreReg(m, &success);
12579
if (!success)
12580
return false;
12581
12582
uint32_t offset;
12583
if (register_index)
12584
offset = Rm;
12585
else
12586
offset = ebytes;
12587
12588
context.type = eContextAdjustBaseRegister;
12589
std::optional<RegisterInfo> base_reg =
12590
GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
12591
context.SetRegisterPlusOffset(*base_reg, offset);
12592
12593
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12594
Rn + offset))
12595
return false;
12596
}
12597
12598
// replicated_element = Replicate(MemU[address,ebytes], elements);
12599
12600
context.type = eContextRegisterLoad;
12601
uint64_t word = MemURead(context, address, ebytes, 0, &success);
12602
if (!success)
12603
return false;
12604
12605
uint64_t replicated_element = 0;
12606
uint32_t esize = ebytes * 8;
12607
for (uint32_t e = 0; e < elements; ++e)
12608
replicated_element =
12609
(replicated_element << esize) | Bits64(word, esize - 1, 0);
12610
12611
// for r = 0 to regs-1
12612
for (uint32_t r = 0; r < regs; ++r) {
12613
// D[d+r] = replicated_element;
12614
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_d0 + d + r,
12615
replicated_element))
12616
return false;
12617
}
12618
}
12619
return true;
12620
}
12621
12622
// B6.2.13 SUBS PC, LR and related instructions The SUBS PC, LR, #<const?
12623
// instruction provides an exception return without the use of the stack. It
12624
// subtracts the immediate constant from the LR, branches to the resulting
12625
// address, and also copies the SPSR to the CPSR.
12626
bool EmulateInstructionARM::EmulateSUBSPcLrEtc(const uint32_t opcode,
12627
const ARMEncoding encoding) {
12628
#if 0
12629
if ConditionPassed() then
12630
EncodingSpecificOperations();
12631
if CurrentInstrSet() == InstrSet_ThumbEE then
12632
UNPREDICTABLE;
12633
operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
12634
case opcode of
12635
when '0000' result = R[n] AND operand2; // AND
12636
when '0001' result = R[n] EOR operand2; // EOR
12637
when '0010' (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB
12638
when '0011' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB
12639
when '0100' (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD
12640
when '0101' (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12641
when '0110' (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12642
when '0111' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12643
when '1100' result = R[n] OR operand2; // ORR
12644
when '1101' result = operand2; // MOV
12645
when '1110' result = R[n] AND NOT(operand2); // BIC
12646
when '1111' result = NOT(operand2); // MVN
12647
CPSRWriteByInstr(SPSR[], '1111', TRUE);
12648
BranchWritePC(result);
12649
#endif
12650
12651
bool success = false;
12652
12653
if (ConditionPassed(opcode)) {
12654
uint32_t n;
12655
uint32_t m;
12656
uint32_t imm32;
12657
bool register_form;
12658
ARM_ShifterType shift_t;
12659
uint32_t shift_n;
12660
uint32_t code;
12661
12662
switch (encoding) {
12663
case eEncodingT1:
12664
// if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE n = 14;
12665
// imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = '0010';
12666
// // = SUB
12667
n = 14;
12668
imm32 = Bits32(opcode, 7, 0);
12669
register_form = false;
12670
code = 2;
12671
12672
// if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
12673
if (InITBlock() && !LastInITBlock())
12674
return false;
12675
12676
break;
12677
12678
case eEncodingA1:
12679
// n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
12680
n = Bits32(opcode, 19, 16);
12681
imm32 = ARMExpandImm(opcode);
12682
register_form = false;
12683
code = Bits32(opcode, 24, 21);
12684
12685
break;
12686
12687
case eEncodingA2:
12688
// n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
12689
n = Bits32(opcode, 19, 16);
12690
m = Bits32(opcode, 3, 0);
12691
register_form = true;
12692
12693
// (shift_t, shift_n) = DecodeImmShift(type, imm5);
12694
shift_n = DecodeImmShiftARM(opcode, shift_t);
12695
12696
break;
12697
12698
default:
12699
return false;
12700
}
12701
12702
// operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C)
12703
// else imm32;
12704
uint32_t operand2;
12705
if (register_form) {
12706
uint32_t Rm = ReadCoreReg(m, &success);
12707
if (!success)
12708
return false;
12709
12710
operand2 = Shift(Rm, shift_t, shift_n, APSR_C, &success);
12711
if (!success)
12712
return false;
12713
} else {
12714
operand2 = imm32;
12715
}
12716
12717
uint32_t Rn = ReadCoreReg(n, &success);
12718
if (!success)
12719
return false;
12720
12721
AddWithCarryResult result;
12722
12723
// case opcode of
12724
switch (code) {
12725
case 0: // when '0000'
12726
// result = R[n] AND operand2; // AND
12727
result.result = Rn & operand2;
12728
break;
12729
12730
case 1: // when '0001'
12731
// result = R[n] EOR operand2; // EOR
12732
result.result = Rn ^ operand2;
12733
break;
12734
12735
case 2: // when '0010'
12736
// (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB
12737
result = AddWithCarry(Rn, ~(operand2), 1);
12738
break;
12739
12740
case 3: // when '0011'
12741
// (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB
12742
result = AddWithCarry(~(Rn), operand2, 1);
12743
break;
12744
12745
case 4: // when '0100'
12746
// (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD
12747
result = AddWithCarry(Rn, operand2, 0);
12748
break;
12749
12750
case 5: // when '0101'
12751
// (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12752
result = AddWithCarry(Rn, operand2, APSR_C);
12753
break;
12754
12755
case 6: // when '0110'
12756
// (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12757
result = AddWithCarry(Rn, ~(operand2), APSR_C);
12758
break;
12759
12760
case 7: // when '0111'
12761
// (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12762
result = AddWithCarry(~(Rn), operand2, APSR_C);
12763
break;
12764
12765
case 10: // when '1100'
12766
// result = R[n] OR operand2; // ORR
12767
result.result = Rn | operand2;
12768
break;
12769
12770
case 11: // when '1101'
12771
// result = operand2; // MOV
12772
result.result = operand2;
12773
break;
12774
12775
case 12: // when '1110'
12776
// result = R[n] AND NOT(operand2); // BIC
12777
result.result = Rn & ~(operand2);
12778
break;
12779
12780
case 15: // when '1111'
12781
// result = NOT(operand2); // MVN
12782
result.result = ~(operand2);
12783
break;
12784
12785
default:
12786
return false;
12787
}
12788
// CPSRWriteByInstr(SPSR[], '1111', TRUE);
12789
12790
// For now, in emulation mode, we don't have access to the SPSR, so we will
12791
// use the CPSR instead, and hope for the best.
12792
uint32_t spsr =
12793
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success);
12794
if (!success)
12795
return false;
12796
12797
CPSRWriteByInstr(spsr, 15, true);
12798
12799
// BranchWritePC(result);
12800
EmulateInstruction::Context context;
12801
context.type = eContextAdjustPC;
12802
context.SetImmediate(result.result);
12803
12804
BranchWritePC(context, result.result);
12805
}
12806
return true;
12807
}
12808
12809
EmulateInstructionARM::ARMOpcode *
12810
EmulateInstructionARM::GetARMOpcodeForInstruction(const uint32_t opcode,
12811
uint32_t arm_isa) {
12812
static ARMOpcode g_arm_opcodes[] = {
12813
// Prologue instructions
12814
12815
// push register(s)
12816
{0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12817
&EmulateInstructionARM::EmulatePUSH, "push <registers>"},
12818
{0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32,
12819
&EmulateInstructionARM::EmulatePUSH, "push <register>"},
12820
12821
// set r7 to point to a stack offset
12822
{0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12823
&EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>"},
12824
{0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12825
&EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
12826
// copy the stack pointer to ip
12827
{0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32,
12828
&EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp"},
12829
{0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12830
&EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>"},
12831
{0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12832
&EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
12833
12834
// adjust the stack pointer
12835
{0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12836
&EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
12837
{0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12838
&EmulateInstructionARM::EmulateSUBSPReg,
12839
"sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},
12840
12841
// push one register
12842
// if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
12843
{0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12844
&EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!"},
12845
12846
// vector push consecutive extension register(s)
12847
{0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32,
12848
&EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12849
{0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,
12850
&EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
12851
12852
// Epilogue instructions
12853
12854
{0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12855
&EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12856
{0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32,
12857
&EmulateInstructionARM::EmulatePOP, "pop <register>"},
12858
{0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32,
12859
&EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12860
{0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,
12861
&EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
12862
12863
// Supervisor Call (previously Software Interrupt)
12864
{0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12865
&EmulateInstructionARM::EmulateSVC, "svc #imm24"},
12866
12867
// Branch instructions
12868
// To resolve ambiguity, "blx <label>" should come before "b #imm24" and
12869
// "bl <label>".
12870
{0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32,
12871
&EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12872
{0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12873
&EmulateInstructionARM::EmulateB, "b #imm24"},
12874
{0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12875
&EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
12876
{0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32,
12877
&EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
12878
// for example, "bx lr"
12879
{0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32,
12880
&EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
12881
// bxj
12882
{0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32,
12883
&EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
12884
12885
// Data-processing instructions
12886
// adc (immediate)
12887
{0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12888
&EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
12889
// adc (register)
12890
{0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12891
&EmulateInstructionARM::EmulateADCReg,
12892
"adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12893
// add (immediate)
12894
{0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12895
&EmulateInstructionARM::EmulateADDImmARM,
12896
"add{s}<c> <Rd>, <Rn>, #const"},
12897
// add (register)
12898
{0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12899
&EmulateInstructionARM::EmulateADDReg,
12900
"add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12901
// add (register-shifted register)
12902
{0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32,
12903
&EmulateInstructionARM::EmulateADDRegShift,
12904
"add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
12905
// adr
12906
{0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12907
&EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12908
{0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32,
12909
&EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
12910
// and (immediate)
12911
{0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12912
&EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
12913
// and (register)
12914
{0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12915
&EmulateInstructionARM::EmulateANDReg,
12916
"and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12917
// bic (immediate)
12918
{0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12919
&EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
12920
// bic (register)
12921
{0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12922
&EmulateInstructionARM::EmulateBICReg,
12923
"bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12924
// eor (immediate)
12925
{0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12926
&EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
12927
// eor (register)
12928
{0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12929
&EmulateInstructionARM::EmulateEORReg,
12930
"eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12931
// orr (immediate)
12932
{0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12933
&EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
12934
// orr (register)
12935
{0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12936
&EmulateInstructionARM::EmulateORRReg,
12937
"orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12938
// rsb (immediate)
12939
{0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12940
&EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
12941
// rsb (register)
12942
{0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12943
&EmulateInstructionARM::EmulateRSBReg,
12944
"rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12945
// rsc (immediate)
12946
{0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12947
&EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
12948
// rsc (register)
12949
{0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12950
&EmulateInstructionARM::EmulateRSCReg,
12951
"rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12952
// sbc (immediate)
12953
{0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12954
&EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
12955
// sbc (register)
12956
{0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12957
&EmulateInstructionARM::EmulateSBCReg,
12958
"sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12959
// sub (immediate, ARM)
12960
{0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12961
&EmulateInstructionARM::EmulateSUBImmARM,
12962
"sub{s}<c> <Rd>, <Rn>, #<const>"},
12963
// sub (sp minus immediate)
12964
{0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12965
&EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
12966
// sub (register)
12967
{0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12968
&EmulateInstructionARM::EmulateSUBReg,
12969
"sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
12970
// teq (immediate)
12971
{0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12972
&EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
12973
// teq (register)
12974
{0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12975
&EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
12976
// tst (immediate)
12977
{0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12978
&EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
12979
// tst (register)
12980
{0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12981
&EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
12982
12983
// mov (immediate)
12984
{0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12985
&EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
12986
{0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,
12987
&EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>"},
12988
// mov (register)
12989
{0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12990
&EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
12991
// mvn (immediate)
12992
{0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12993
&EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
12994
// mvn (register)
12995
{0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12996
&EmulateInstructionARM::EmulateMVNReg,
12997
"mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
12998
// cmn (immediate)
12999
{0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13000
&EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
13001
// cmn (register)
13002
{0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13003
&EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
13004
// cmp (immediate)
13005
{0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13006
&EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
13007
// cmp (register)
13008
{0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13009
&EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
13010
// asr (immediate)
13011
{0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32,
13012
&EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
13013
// asr (register)
13014
{0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32,
13015
&EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
13016
// lsl (immediate)
13017
{0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13018
&EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
13019
// lsl (register)
13020
{0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32,
13021
&EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
13022
// lsr (immediate)
13023
{0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32,
13024
&EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
13025
// lsr (register)
13026
{0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32,
13027
&EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
13028
// rrx is a special case encoding of ror (immediate)
13029
{0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32,
13030
&EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
13031
// ror (immediate)
13032
{0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32,
13033
&EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
13034
// ror (register)
13035
{0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32,
13036
&EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
13037
// mul
13038
{0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32,
13039
&EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>"},
13040
13041
// subs pc, lr and related instructions
13042
{0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13043
&EmulateInstructionARM::EmulateSUBSPcLrEtc,
13044
"<opc>S<c> PC,#<const> | <Rn>,#<const>"},
13045
{0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32,
13046
&EmulateInstructionARM::EmulateSUBSPcLrEtc,
13047
"<opc>S<c> PC,<Rn>,<Rm{,<shift>}"},
13048
13049
// Load instructions
13050
{0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13051
&EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"},
13052
{0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13053
&EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>"},
13054
{0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13055
&EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"},
13056
{0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13057
&EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>"},
13058
{0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13059
&EmulateInstructionARM::EmulateLDRImmediateARM,
13060
"ldr<c> <Rt> [<Rn> {#+/-<imm12>}]"},
13061
{0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13062
&EmulateInstructionARM::EmulateLDRRegister,
13063
"ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}"},
13064
{0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13065
&EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
13066
{0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13067
&EmulateInstructionARM::EmulateLDRBRegister,
13068
"ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}"},
13069
{0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13070
&EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"},
13071
{0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13072
&EmulateInstructionARM::EmulateLDRHRegister,
13073
"ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13074
{0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13075
&EmulateInstructionARM::EmulateLDRSBImmediate,
13076
"ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]"},
13077
{0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13078
&EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>"},
13079
{0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13080
&EmulateInstructionARM::EmulateLDRSBRegister,
13081
"ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13082
{0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13083
&EmulateInstructionARM::EmulateLDRSHImmediate,
13084
"ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
13085
{0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13086
&EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"},
13087
{0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13088
&EmulateInstructionARM::EmulateLDRSHRegister,
13089
"ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13090
{0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13091
&EmulateInstructionARM::EmulateLDRDImmediate,
13092
"ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
13093
{0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13094
&EmulateInstructionARM::EmulateLDRDRegister,
13095
"ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
13096
{0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13097
&EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13098
{0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13099
&EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13100
{0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13101
&EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13102
{0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13103
&EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
13104
{0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13105
&EmulateInstructionARM::EmulateVLD1Multiple,
13106
"vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13107
{0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13108
&EmulateInstructionARM::EmulateVLD1Single,
13109
"vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13110
{0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13111
&EmulateInstructionARM::EmulateVLD1SingleAll,
13112
"vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13113
13114
// Store instructions
13115
{0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13116
&EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"},
13117
{0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13118
&EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>"},
13119
{0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13120
&EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"},
13121
{0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13122
&EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>"},
13123
{0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13124
&EmulateInstructionARM::EmulateSTRRegister,
13125
"str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}"},
13126
{0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13127
&EmulateInstructionARM::EmulateSTRHRegister,
13128
"strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}"},
13129
{0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13130
&EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
13131
{0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13132
&EmulateInstructionARM::EmulateSTRBImmARM,
13133
"strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
13134
{0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13135
&EmulateInstructionARM::EmulateSTRImmARM,
13136
"str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
13137
{0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13138
&EmulateInstructionARM::EmulateSTRDImm,
13139
"strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
13140
{0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13141
&EmulateInstructionARM::EmulateSTRDReg,
13142
"strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
13143
{0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13144
&EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
13145
{0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13146
&EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
13147
{0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13148
&EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
13149
{0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13150
&EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
13151
{0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13152
&EmulateInstructionARM::EmulateVST1Multiple,
13153
"vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13154
{0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13155
&EmulateInstructionARM::EmulateVST1Single,
13156
"vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13157
13158
// Other instructions
13159
{0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13160
&EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}"},
13161
{0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13162
&EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}"},
13163
{0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13164
&EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}"},
13165
{0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13166
&EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}"},
13167
{0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13168
&EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}"}
13169
13170
};
13171
static const size_t k_num_arm_opcodes = std::size(g_arm_opcodes);
13172
13173
for (size_t i = 0; i < k_num_arm_opcodes; ++i) {
13174
if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value &&
13175
(g_arm_opcodes[i].variants & arm_isa) != 0)
13176
return &g_arm_opcodes[i];
13177
}
13178
return nullptr;
13179
}
13180
13181
EmulateInstructionARM::ARMOpcode *
13182
EmulateInstructionARM::GetThumbOpcodeForInstruction(const uint32_t opcode,
13183
uint32_t arm_isa) {
13184
13185
static ARMOpcode g_thumb_opcodes[] = {
13186
// Prologue instructions
13187
13188
// push register(s)
13189
{0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16,
13190
&EmulateInstructionARM::EmulatePUSH, "push <registers>"},
13191
{0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13192
&EmulateInstructionARM::EmulatePUSH, "push.w <registers>"},
13193
{0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13194
&EmulateInstructionARM::EmulatePUSH, "push.w <register>"},
13195
13196
// set r7 to point to a stack offset
13197
{0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13198
&EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm"},
13199
// copy the stack pointer to r7
13200
{0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16,
13201
&EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp"},
13202
// move from high register to low register (comes after "mov r7, sp" to
13203
// resolve ambiguity)
13204
{0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16,
13205
&EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15"},
13206
13207
// PC-relative load into register (see also EmulateADDSPRm)
13208
{0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13209
&EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
13210
13211
// adjust the stack pointer
13212
{0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16,
13213
&EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
13214
{0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16,
13215
&EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
13216
{0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13217
&EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
13218
{0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13219
&EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
13220
{0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13221
&EmulateInstructionARM::EmulateSUBSPReg,
13222
"sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},
13223
13224
// vector push consecutive extension register(s)
13225
{0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13226
&EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
13227
{0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13228
&EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
13229
13230
// Epilogue instructions
13231
13232
{0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13233
&EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
13234
{0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16,
13235
&EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
13236
{0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13237
&EmulateInstructionARM::EmulatePOP, "pop <registers>"},
13238
{0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13239
&EmulateInstructionARM::EmulatePOP, "pop.w <registers>"},
13240
{0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13241
&EmulateInstructionARM::EmulatePOP, "pop.w <register>"},
13242
{0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13243
&EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
13244
{0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13245
&EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
13246
13247
// Supervisor Call (previously Software Interrupt)
13248
{0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13249
&EmulateInstructionARM::EmulateSVC, "svc #imm8"},
13250
13251
// If Then makes up to four following instructions conditional.
13252
// The next 5 opcode _must_ come before the if then instruction
13253
{0xffffffff, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13254
&EmulateInstructionARM::EmulateNop, "nop"},
13255
{0xffffffff, 0x0000bf10, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13256
&EmulateInstructionARM::EmulateNop, "nop YIELD (yield hint)"},
13257
{0xffffffff, 0x0000bf20, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13258
&EmulateInstructionARM::EmulateNop, "nop WFE (wait for event hint)"},
13259
{0xffffffff, 0x0000bf30, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13260
&EmulateInstructionARM::EmulateNop, "nop WFI (wait for interrupt hint)"},
13261
{0xffffffff, 0x0000bf40, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13262
&EmulateInstructionARM::EmulateNop, "nop SEV (send event hint)"},
13263
{0xffffff00, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13264
&EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
13265
13266
// Branch instructions
13267
// To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
13268
{0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13269
&EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
13270
{0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16,
13271
&EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
13272
{0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13273
&EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
13274
{0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13275
&EmulateInstructionARM::EmulateB,
13276
"b<c>.w #imm8 (outside or last in IT)"},
13277
// J1 == J2 == 1
13278
{0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32,
13279
&EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
13280
// J1 == J2 == 1
13281
{0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32,
13282
&EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
13283
{0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16,
13284
&EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
13285
// for example, "bx lr"
13286
{0xffffff87, 0x00004700, ARMvAll, eEncodingT1, No_VFP, eSize32,
13287
&EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
13288
// bxj
13289
{0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32,
13290
&EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
13291
// compare and branch
13292
{0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13293
&EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
13294
// table branch byte
13295
{0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13296
&EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
13297
// table branch halfword
13298
{0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13299
&EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
13300
13301
// Data-processing instructions
13302
// adc (immediate)
13303
{0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13304
&EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
13305
// adc (register)
13306
{0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16,
13307
&EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
13308
{0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13309
&EmulateInstructionARM::EmulateADCReg,
13310
"adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13311
// add (register)
13312
{0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13313
&EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
13314
// Make sure "add sp, <Rm>" comes before this instruction, so there's no
13315
// ambiguity decoding the two.
13316
{0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16,
13317
&EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
13318
// adr
13319
{0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13320
&EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
13321
{0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13322
&EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
13323
{0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13324
&EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
13325
// and (immediate)
13326
{0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13327
&EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
13328
// and (register)
13329
{0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13330
&EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
13331
{0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13332
&EmulateInstructionARM::EmulateANDReg,
13333
"and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13334
// bic (immediate)
13335
{0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13336
&EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
13337
// bic (register)
13338
{0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16,
13339
&EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
13340
{0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13341
&EmulateInstructionARM::EmulateBICReg,
13342
"bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13343
// eor (immediate)
13344
{0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13345
&EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
13346
// eor (register)
13347
{0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16,
13348
&EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
13349
{0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13350
&EmulateInstructionARM::EmulateEORReg,
13351
"eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13352
// orr (immediate)
13353
{0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13354
&EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
13355
// orr (register)
13356
{0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16,
13357
&EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
13358
{0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13359
&EmulateInstructionARM::EmulateORRReg,
13360
"orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13361
// rsb (immediate)
13362
{0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16,
13363
&EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
13364
{0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13365
&EmulateInstructionARM::EmulateRSBImm,
13366
"rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
13367
// rsb (register)
13368
{0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13369
&EmulateInstructionARM::EmulateRSBReg,
13370
"rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13371
// sbc (immediate)
13372
{0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13373
&EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
13374
// sbc (register)
13375
{0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16,
13376
&EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
13377
{0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13378
&EmulateInstructionARM::EmulateSBCReg,
13379
"sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13380
// add (immediate, Thumb)
13381
{0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13382
&EmulateInstructionARM::EmulateADDImmThumb,
13383
"adds|add<c> <Rd>,<Rn>,#<imm3>"},
13384
{0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,
13385
&EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>"},
13386
{0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13387
&EmulateInstructionARM::EmulateADDImmThumb,
13388
"add{s}<c>.w <Rd>,<Rn>,#<const>"},
13389
{0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13390
&EmulateInstructionARM::EmulateADDImmThumb,
13391
"addw<c> <Rd>,<Rn>,#<imm12>"},
13392
// sub (immediate, Thumb)
13393
{0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13394
&EmulateInstructionARM::EmulateSUBImmThumb,
13395
"subs|sub<c> <Rd>, <Rn> #imm3"},
13396
{0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16,
13397
&EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
13398
{0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13399
&EmulateInstructionARM::EmulateSUBImmThumb,
13400
"sub{s}<c>.w <Rd>, <Rn>, #<const>"},
13401
{0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13402
&EmulateInstructionARM::EmulateSUBImmThumb,
13403
"subw<c> <Rd>, <Rn>, #imm12"},
13404
// sub (sp minus immediate)
13405
{0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13406
&EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
13407
{0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13408
&EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
13409
// sub (register)
13410
{0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13411
&EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
13412
{0xffe08000, 0xeba00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13413
&EmulateInstructionARM::EmulateSUBReg,
13414
"sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"},
13415
// teq (immediate)
13416
{0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13417
&EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
13418
// teq (register)
13419
{0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13420
&EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
13421
// tst (immediate)
13422
{0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13423
&EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
13424
// tst (register)
13425
{0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16,
13426
&EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
13427
{0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13428
&EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
13429
13430
// move from high register to high register
13431
{0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16,
13432
&EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
13433
// move from low register to low register
13434
{0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16,
13435
&EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
13436
// mov{s}<c>.w <Rd>, <Rm>
13437
{0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13438
&EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
13439
// move immediate
13440
{0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13441
&EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
13442
{0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13443
&EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
13444
{0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13445
&EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
13446
// mvn (immediate)
13447
{0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13448
&EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
13449
// mvn (register)
13450
{0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13451
&EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
13452
{0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13453
&EmulateInstructionARM::EmulateMVNReg,
13454
"mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
13455
// cmn (immediate)
13456
{0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13457
&EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
13458
// cmn (register)
13459
{0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13460
&EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
13461
{0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13462
&EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
13463
// cmp (immediate)
13464
{0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13465
&EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
13466
{0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13467
&EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
13468
// cmp (register) (Rn and Rm both from r0-r7)
13469
{0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16,
13470
&EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
13471
// cmp (register) (Rn and Rm not both from r0-r7)
13472
{0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16,
13473
&EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
13474
{0xfff08f00, 0xebb00f00, ARMvAll, eEncodingT3, No_VFP, eSize16,
13475
&EmulateInstructionARM::EmulateCMPReg,
13476
"cmp<c>.w <Rn>, <Rm> {, <shift>}"},
13477
// asr (immediate)
13478
{0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13479
&EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
13480
{0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13481
&EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
13482
// asr (register)
13483
{0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16,
13484
&EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
13485
{0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13486
&EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
13487
// lsl (immediate)
13488
{0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13489
&EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
13490
{0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13491
&EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
13492
// lsl (register)
13493
{0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16,
13494
&EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
13495
{0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13496
&EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
13497
// lsr (immediate)
13498
{0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13499
&EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
13500
{0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13501
&EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
13502
// lsr (register)
13503
{0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13504
&EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
13505
{0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13506
&EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
13507
// rrx is a special case encoding of ror (immediate)
13508
{0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13509
&EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
13510
// ror (immediate)
13511
{0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13512
&EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
13513
// ror (register)
13514
{0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13515
&EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
13516
{0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13517
&EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
13518
// mul
13519
{0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13520
&EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>"},
13521
// mul
13522
{0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13523
&EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>"},
13524
13525
// subs pc, lr and related instructions
13526
{0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13527
&EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>"},
13528
13529
// RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE
13530
// LDM.. Instructions in this table;
13531
// otherwise the wrong instructions will be selected.
13532
13533
{0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13534
&EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}"},
13535
{0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13536
&EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}"},
13537
13538
// Load instructions
13539
{0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13540
&EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"},
13541
{0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13542
&EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>"},
13543
{0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13544
&EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"},
13545
{0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13546
&EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
13547
{0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,
13548
&EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
13549
{0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13550
&EmulateInstructionARM::EmulateLDRRtRnImm,
13551
"ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
13552
{0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13553
&EmulateInstructionARM::EmulateLDRRtRnImm,
13554
"ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
13555
// Thumb2 PC-relative load into register
13556
{0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13557
&EmulateInstructionARM::EmulateLDRRtPCRelative,
13558
"ldr<c>.w <Rt>, [PC, +/-#imm}]"},
13559
{0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13560
&EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]"},
13561
{0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13562
&EmulateInstructionARM::EmulateLDRRegister,
13563
"ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]"},
13564
{0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13565
&EmulateInstructionARM::EmulateLDRBImmediate,
13566
"ldrb<c> <Rt>,[<Rn>{,#<imm5>}]"},
13567
{0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13568
&EmulateInstructionARM::EmulateLDRBImmediate,
13569
"ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]"},
13570
{0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13571
&EmulateInstructionARM::EmulateLDRBImmediate,
13572
"ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}"},
13573
{0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13574
&EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]"},
13575
{0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13576
&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]"},
13577
{0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13578
&EmulateInstructionARM::EmulateLDRBRegister,
13579
"ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},
13580
{0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13581
&EmulateInstructionARM::EmulateLDRHImmediate,
13582
"ldrh<c> <Rt>, [<Rn>{,#<imm>}]"},
13583
{0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13584
&EmulateInstructionARM::EmulateLDRHImmediate,
13585
"ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]"},
13586
{0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13587
&EmulateInstructionARM::EmulateLDRHImmediate,
13588
"ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}"},
13589
{0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13590
&EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"},
13591
{0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13592
&EmulateInstructionARM::EmulateLDRHRegister,
13593
"ldrh<c> <Rt>, [<Rn>,<Rm>]"},
13594
{0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13595
&EmulateInstructionARM::EmulateLDRHRegister,
13596
"ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13597
{0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13598
&EmulateInstructionARM::EmulateLDRSBImmediate,
13599
"ldrsb<c> <Rt>,[<Rn>,#<imm12>]"},
13600
{0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13601
&EmulateInstructionARM::EmulateLDRSBImmediate,
13602
"ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]"},
13603
{0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13604
&EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>"},
13605
{0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13606
&EmulateInstructionARM::EmulateLDRSBRegister,
13607
"ldrsb<c> <Rt>,[<Rn>,<Rm>]"},
13608
{0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13609
&EmulateInstructionARM::EmulateLDRSBRegister,
13610
"ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},
13611
{0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13612
&EmulateInstructionARM::EmulateLDRSHImmediate,
13613
"ldrsh<c> <Rt>,[<Rn>,#<imm12>]"},
13614
{0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13615
&EmulateInstructionARM::EmulateLDRSHImmediate,
13616
"ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]"},
13617
{0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13618
&EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"},
13619
{0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13620
&EmulateInstructionARM::EmulateLDRSHRegister,
13621
"ldrsh<c> <Rt>,[<Rn>,<Rm>]"},
13622
{0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13623
&EmulateInstructionARM::EmulateLDRSHRegister,
13624
"ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13625
{0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13626
&EmulateInstructionARM::EmulateLDRDImmediate,
13627
"ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
13628
{0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13629
&EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13630
{0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13631
&EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13632
{0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13633
&EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13634
{0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13635
&EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
13636
{0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13637
&EmulateInstructionARM::EmulateVLD1Multiple,
13638
"vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
13639
{0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13640
&EmulateInstructionARM::EmulateVLD1Single,
13641
"vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
13642
{0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13643
&EmulateInstructionARM::EmulateVLD1SingleAll,
13644
"vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13645
13646
// Store instructions
13647
{0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13648
&EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"},
13649
{0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13650
&EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>"},
13651
{0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13652
&EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"},
13653
{0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13654
&EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]"},
13655
{0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,
13656
&EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]"},
13657
{0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13658
&EmulateInstructionARM::EmulateSTRThumb,
13659
"str<c>.w <Rt>, [<Rn>,#<imm12>]"},
13660
{0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13661
&EmulateInstructionARM::EmulateSTRThumb,
13662
"str<c> <Rt>, [<Rn>,#+/-<imm8>]"},
13663
{0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13664
&EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]"},
13665
{0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13666
&EmulateInstructionARM::EmulateSTRRegister,
13667
"str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]"},
13668
{0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13669
&EmulateInstructionARM::EmulateSTRBThumb,
13670
"strb<c> <Rt>, [<Rn>, #<imm5>]"},
13671
{0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13672
&EmulateInstructionARM::EmulateSTRBThumb,
13673
"strb<c>.w <Rt>, [<Rn>, #<imm12>]"},
13674
{0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13675
&EmulateInstructionARM::EmulateSTRBThumb,
13676
"strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}"},
13677
{0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13678
&EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]"},
13679
{0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13680
&EmulateInstructionARM::EmulateSTRHRegister,
13681
"strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13682
{0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13683
&EmulateInstructionARM::EmulateSTREX,
13684
"strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]"},
13685
{0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13686
&EmulateInstructionARM::EmulateSTRDImm,
13687
"strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
13688
{0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13689
&EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
13690
{0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13691
&EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
13692
{0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13693
&EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13694
{0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13695
&EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
13696
{0xffb00000, 0xf9000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13697
&EmulateInstructionARM::EmulateVST1Multiple,
13698
"vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13699
{0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13700
&EmulateInstructionARM::EmulateVST1Single,
13701
"vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13702
13703
// Other instructions
13704
{0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13705
&EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>"},
13706
{0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32,
13707
&EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}"},
13708
{0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13709
&EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>"},
13710
{0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13711
&EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}"},
13712
{0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13713
&EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>"},
13714
{0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13715
&EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}"},
13716
{0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13717
&EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>"},
13718
{0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13719
&EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}"},
13720
};
13721
13722
const size_t k_num_thumb_opcodes = std::size(g_thumb_opcodes);
13723
for (size_t i = 0; i < k_num_thumb_opcodes; ++i) {
13724
if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value &&
13725
(g_thumb_opcodes[i].variants & arm_isa) != 0)
13726
return &g_thumb_opcodes[i];
13727
}
13728
return nullptr;
13729
}
13730
13731
bool EmulateInstructionARM::SetArchitecture(const ArchSpec &arch) {
13732
m_arch = arch;
13733
m_arm_isa = 0;
13734
llvm::StringRef arch_cstr = arch.GetArchitectureName();
13735
if (arch_cstr.equals_insensitive("armv4t"))
13736
m_arm_isa = ARMv4T;
13737
else if (arch_cstr.equals_insensitive("armv5tej"))
13738
m_arm_isa = ARMv5TEJ;
13739
else if (arch_cstr.equals_insensitive("armv5te"))
13740
m_arm_isa = ARMv5TE;
13741
else if (arch_cstr.equals_insensitive("armv5t"))
13742
m_arm_isa = ARMv5T;
13743
else if (arch_cstr.equals_insensitive("armv6k"))
13744
m_arm_isa = ARMv6K;
13745
else if (arch_cstr.equals_insensitive("armv6t2"))
13746
m_arm_isa = ARMv6T2;
13747
else if (arch_cstr.equals_insensitive("armv7s"))
13748
m_arm_isa = ARMv7S;
13749
else if (arch_cstr.equals_insensitive("arm"))
13750
m_arm_isa = ARMvAll;
13751
else if (arch_cstr.equals_insensitive("thumb"))
13752
m_arm_isa = ARMvAll;
13753
else if (arch_cstr.starts_with_insensitive("armv4"))
13754
m_arm_isa = ARMv4;
13755
else if (arch_cstr.starts_with_insensitive("armv6"))
13756
m_arm_isa = ARMv6;
13757
else if (arch_cstr.starts_with_insensitive("armv7"))
13758
m_arm_isa = ARMv7;
13759
else if (arch_cstr.starts_with_insensitive("armv8"))
13760
m_arm_isa = ARMv8;
13761
return m_arm_isa != 0;
13762
}
13763
13764
bool EmulateInstructionARM::SetInstruction(const Opcode &insn_opcode,
13765
const Address &inst_addr,
13766
Target *target) {
13767
if (EmulateInstruction::SetInstruction(insn_opcode, inst_addr, target)) {
13768
if (m_arch.GetTriple().getArch() == llvm::Triple::thumb ||
13769
m_arch.IsAlwaysThumbInstructions())
13770
m_opcode_mode = eModeThumb;
13771
else {
13772
AddressClass addr_class = inst_addr.GetAddressClass();
13773
13774
if ((addr_class == AddressClass::eCode) ||
13775
(addr_class == AddressClass::eUnknown))
13776
m_opcode_mode = eModeARM;
13777
else if (addr_class == AddressClass::eCodeAlternateISA)
13778
m_opcode_mode = eModeThumb;
13779
else
13780
return false;
13781
}
13782
if (m_opcode_mode == eModeThumb || m_arch.IsAlwaysThumbInstructions())
13783
m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T;
13784
else
13785
m_opcode_cpsr = CPSR_MODE_USR;
13786
return true;
13787
}
13788
return false;
13789
}
13790
13791
bool EmulateInstructionARM::ReadInstruction() {
13792
bool success = false;
13793
m_opcode_cpsr = ReadRegisterUnsigned(eRegisterKindGeneric,
13794
LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
13795
if (success) {
13796
addr_t pc =
13797
ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
13798
LLDB_INVALID_ADDRESS, &success);
13799
if (success) {
13800
Context read_inst_context;
13801
read_inst_context.type = eContextReadOpcode;
13802
read_inst_context.SetNoArgs();
13803
13804
if ((m_opcode_cpsr & MASK_CPSR_T) || m_arch.IsAlwaysThumbInstructions()) {
13805
m_opcode_mode = eModeThumb;
13806
uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
13807
13808
if (success) {
13809
if ((thumb_opcode & 0xe000) != 0xe000 ||
13810
((thumb_opcode & 0x1800u) == 0)) {
13811
m_opcode.SetOpcode16(thumb_opcode, GetByteOrder());
13812
} else {
13813
m_opcode.SetOpcode32(
13814
(thumb_opcode << 16) |
13815
MemARead(read_inst_context, pc + 2, 2, 0, &success),
13816
GetByteOrder());
13817
}
13818
}
13819
} else {
13820
m_opcode_mode = eModeARM;
13821
m_opcode.SetOpcode32(MemARead(read_inst_context, pc, 4, 0, &success),
13822
GetByteOrder());
13823
}
13824
13825
if (!m_ignore_conditions) {
13826
// If we are not ignoreing the conditions then init the it session from
13827
// the current value of cpsr.
13828
uint32_t it = (Bits32(m_opcode_cpsr, 15, 10) << 2) |
13829
Bits32(m_opcode_cpsr, 26, 25);
13830
if (it != 0)
13831
m_it_session.InitIT(it);
13832
}
13833
}
13834
}
13835
if (!success) {
13836
m_opcode_mode = eModeInvalid;
13837
m_addr = LLDB_INVALID_ADDRESS;
13838
}
13839
return success;
13840
}
13841
13842
uint32_t EmulateInstructionARM::ArchVersion() { return m_arm_isa; }
13843
13844
bool EmulateInstructionARM::ConditionPassed(const uint32_t opcode) {
13845
// If we are ignoring conditions, then always return true. this allows us to
13846
// iterate over disassembly code and still emulate an instruction even if we
13847
// don't have all the right bits set in the CPSR register...
13848
if (m_ignore_conditions)
13849
return true;
13850
13851
const uint32_t cond = CurrentCond(opcode);
13852
if (cond == UINT32_MAX)
13853
return false;
13854
13855
bool result = false;
13856
switch (UnsignedBits(cond, 3, 1)) {
13857
case 0:
13858
if (m_opcode_cpsr == 0)
13859
result = true;
13860
else
13861
result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;
13862
break;
13863
case 1:
13864
if (m_opcode_cpsr == 0)
13865
result = true;
13866
else
13867
result = (m_opcode_cpsr & MASK_CPSR_C) != 0;
13868
break;
13869
case 2:
13870
if (m_opcode_cpsr == 0)
13871
result = true;
13872
else
13873
result = (m_opcode_cpsr & MASK_CPSR_N) != 0;
13874
break;
13875
case 3:
13876
if (m_opcode_cpsr == 0)
13877
result = true;
13878
else
13879
result = (m_opcode_cpsr & MASK_CPSR_V) != 0;
13880
break;
13881
case 4:
13882
if (m_opcode_cpsr == 0)
13883
result = true;
13884
else
13885
result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) &&
13886
((m_opcode_cpsr & MASK_CPSR_Z) == 0);
13887
break;
13888
case 5:
13889
if (m_opcode_cpsr == 0)
13890
result = true;
13891
else {
13892
bool n = (m_opcode_cpsr & MASK_CPSR_N);
13893
bool v = (m_opcode_cpsr & MASK_CPSR_V);
13894
result = n == v;
13895
}
13896
break;
13897
case 6:
13898
if (m_opcode_cpsr == 0)
13899
result = true;
13900
else {
13901
bool n = (m_opcode_cpsr & MASK_CPSR_N);
13902
bool v = (m_opcode_cpsr & MASK_CPSR_V);
13903
result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
13904
}
13905
break;
13906
case 7:
13907
// Always execute (cond == 0b1110, or the special 0b1111 which gives
13908
// opcodes different meanings, but always means execution happens.
13909
return true;
13910
}
13911
13912
if (cond & 1)
13913
result = !result;
13914
return result;
13915
}
13916
13917
uint32_t EmulateInstructionARM::CurrentCond(const uint32_t opcode) {
13918
switch (m_opcode_mode) {
13919
case eModeInvalid:
13920
break;
13921
13922
case eModeARM:
13923
return UnsignedBits(opcode, 31, 28);
13924
13925
case eModeThumb:
13926
// For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
13927
// 'cond' field of the encoding.
13928
{
13929
const uint32_t byte_size = m_opcode.GetByteSize();
13930
if (byte_size == 2) {
13931
if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 8) != 0x0f)
13932
return Bits32(opcode, 11, 8);
13933
} else if (byte_size == 4) {
13934
if (Bits32(opcode, 31, 27) == 0x1e && Bits32(opcode, 15, 14) == 0x02 &&
13935
Bits32(opcode, 12, 12) == 0x00 && Bits32(opcode, 25, 22) <= 0x0d) {
13936
return Bits32(opcode, 25, 22);
13937
}
13938
} else
13939
// We have an invalid thumb instruction, let's bail out.
13940
break;
13941
13942
return m_it_session.GetCond();
13943
}
13944
}
13945
return UINT32_MAX; // Return invalid value
13946
}
13947
13948
bool EmulateInstructionARM::InITBlock() {
13949
return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
13950
}
13951
13952
bool EmulateInstructionARM::LastInITBlock() {
13953
return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
13954
}
13955
13956
bool EmulateInstructionARM::BadMode(uint32_t mode) {
13957
13958
switch (mode) {
13959
case 16:
13960
return false; // '10000'
13961
case 17:
13962
return false; // '10001'
13963
case 18:
13964
return false; // '10010'
13965
case 19:
13966
return false; // '10011'
13967
case 22:
13968
return false; // '10110'
13969
case 23:
13970
return false; // '10111'
13971
case 27:
13972
return false; // '11011'
13973
case 31:
13974
return false; // '11111'
13975
default:
13976
return true;
13977
}
13978
return true;
13979
}
13980
13981
bool EmulateInstructionARM::CurrentModeIsPrivileged() {
13982
uint32_t mode = Bits32(m_opcode_cpsr, 4, 0);
13983
13984
if (BadMode(mode))
13985
return false;
13986
13987
if (mode == 16)
13988
return false;
13989
13990
return true;
13991
}
13992
13993
void EmulateInstructionARM::CPSRWriteByInstr(uint32_t value, uint32_t bytemask,
13994
bool affect_execstate) {
13995
bool privileged = CurrentModeIsPrivileged();
13996
13997
uint32_t tmp_cpsr = Bits32(m_opcode_cpsr, 23, 20) << 20;
13998
13999
if (BitIsSet(bytemask, 3)) {
14000
tmp_cpsr = tmp_cpsr | (Bits32(value, 31, 27) << 27);
14001
if (affect_execstate)
14002
tmp_cpsr = tmp_cpsr | (Bits32(value, 26, 24) << 24);
14003
}
14004
14005
if (BitIsSet(bytemask, 2)) {
14006
tmp_cpsr = tmp_cpsr | (Bits32(value, 19, 16) << 16);
14007
}
14008
14009
if (BitIsSet(bytemask, 1)) {
14010
if (affect_execstate)
14011
tmp_cpsr = tmp_cpsr | (Bits32(value, 15, 10) << 10);
14012
tmp_cpsr = tmp_cpsr | (Bit32(value, 9) << 9);
14013
if (privileged)
14014
tmp_cpsr = tmp_cpsr | (Bit32(value, 8) << 8);
14015
}
14016
14017
if (BitIsSet(bytemask, 0)) {
14018
if (privileged)
14019
tmp_cpsr = tmp_cpsr | (Bits32(value, 7, 6) << 6);
14020
if (affect_execstate)
14021
tmp_cpsr = tmp_cpsr | (Bit32(value, 5) << 5);
14022
if (privileged)
14023
tmp_cpsr = tmp_cpsr | Bits32(value, 4, 0);
14024
}
14025
14026
m_opcode_cpsr = tmp_cpsr;
14027
}
14028
14029
bool EmulateInstructionARM::BranchWritePC(const Context &context,
14030
uint32_t addr) {
14031
addr_t target;
14032
14033
// Check the current instruction set.
14034
if (CurrentInstrSet() == eModeARM)
14035
target = addr & 0xfffffffc;
14036
else
14037
target = addr & 0xfffffffe;
14038
14039
return WriteRegisterUnsigned(context, eRegisterKindGeneric,
14040
LLDB_REGNUM_GENERIC_PC, target);
14041
}
14042
14043
// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by
14044
// inspecting addr.
14045
bool EmulateInstructionARM::BXWritePC(Context &context, uint32_t addr) {
14046
addr_t target;
14047
// If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
14048
// we want to record it and issue a WriteRegister callback so the clients can
14049
// track the mode changes accordingly.
14050
bool cpsr_changed = false;
14051
14052
if (BitIsSet(addr, 0)) {
14053
if (CurrentInstrSet() != eModeThumb) {
14054
SelectInstrSet(eModeThumb);
14055
cpsr_changed = true;
14056
}
14057
target = addr & 0xfffffffe;
14058
context.SetISA(eModeThumb);
14059
} else if (BitIsClear(addr, 1)) {
14060
if (CurrentInstrSet() != eModeARM) {
14061
SelectInstrSet(eModeARM);
14062
cpsr_changed = true;
14063
}
14064
target = addr & 0xfffffffc;
14065
context.SetISA(eModeARM);
14066
} else
14067
return false; // address<1:0> == '10' => UNPREDICTABLE
14068
14069
if (cpsr_changed) {
14070
if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
14071
LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
14072
return false;
14073
}
14074
return WriteRegisterUnsigned(context, eRegisterKindGeneric,
14075
LLDB_REGNUM_GENERIC_PC, target);
14076
}
14077
14078
// Dispatches to either BXWritePC or BranchWritePC based on architecture
14079
// versions.
14080
bool EmulateInstructionARM::LoadWritePC(Context &context, uint32_t addr) {
14081
if (ArchVersion() >= ARMv5T)
14082
return BXWritePC(context, addr);
14083
else
14084
return BranchWritePC((const Context)context, addr);
14085
}
14086
14087
// Dispatches to either BXWritePC or BranchWritePC based on architecture
14088
// versions and current instruction set.
14089
bool EmulateInstructionARM::ALUWritePC(Context &context, uint32_t addr) {
14090
if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
14091
return BXWritePC(context, addr);
14092
else
14093
return BranchWritePC((const Context)context, addr);
14094
}
14095
14096
EmulateInstructionARM::Mode EmulateInstructionARM::CurrentInstrSet() {
14097
return m_opcode_mode;
14098
}
14099
14100
// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
14101
// ReadInstruction() is performed. This function has a side effect of updating
14102
// the m_new_inst_cpsr member variable if necessary.
14103
bool EmulateInstructionARM::SelectInstrSet(Mode arm_or_thumb) {
14104
m_new_inst_cpsr = m_opcode_cpsr;
14105
switch (arm_or_thumb) {
14106
default:
14107
return false;
14108
case eModeARM:
14109
// Clear the T bit.
14110
m_new_inst_cpsr &= ~MASK_CPSR_T;
14111
break;
14112
case eModeThumb:
14113
// Set the T bit.
14114
m_new_inst_cpsr |= MASK_CPSR_T;
14115
break;
14116
}
14117
return true;
14118
}
14119
14120
// This function returns TRUE if the processor currently provides support for
14121
// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
14122
// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
14123
bool EmulateInstructionARM::UnalignedSupport() {
14124
return (ArchVersion() >= ARMv7);
14125
}
14126
14127
// The main addition and subtraction instructions can produce status
14128
// information about both unsigned carry and signed overflow conditions. This
14129
// status information can be used to synthesize multi-word additions and
14130
// subtractions.
14131
EmulateInstructionARM::AddWithCarryResult
14132
EmulateInstructionARM::AddWithCarry(uint32_t x, uint32_t y, uint8_t carry_in) {
14133
uint32_t result;
14134
uint8_t carry_out;
14135
uint8_t overflow;
14136
14137
uint64_t unsigned_sum = x + y + carry_in;
14138
int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
14139
14140
result = UnsignedBits(unsigned_sum, 31, 0);
14141
// carry_out = (result == unsigned_sum ? 0 : 1);
14142
overflow = ((int32_t)result == signed_sum ? 0 : 1);
14143
14144
if (carry_in)
14145
carry_out = ((int32_t)x >= (int32_t)(~y)) ? 1 : 0;
14146
else
14147
carry_out = ((int32_t)x > (int32_t)y) ? 1 : 0;
14148
14149
AddWithCarryResult res = {result, carry_out, overflow};
14150
return res;
14151
}
14152
14153
uint32_t EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success) {
14154
lldb::RegisterKind reg_kind;
14155
uint32_t reg_num;
14156
switch (num) {
14157
case SP_REG:
14158
reg_kind = eRegisterKindGeneric;
14159
reg_num = LLDB_REGNUM_GENERIC_SP;
14160
break;
14161
case LR_REG:
14162
reg_kind = eRegisterKindGeneric;
14163
reg_num = LLDB_REGNUM_GENERIC_RA;
14164
break;
14165
case PC_REG:
14166
reg_kind = eRegisterKindGeneric;
14167
reg_num = LLDB_REGNUM_GENERIC_PC;
14168
break;
14169
default:
14170
if (num < SP_REG) {
14171
reg_kind = eRegisterKindDWARF;
14172
reg_num = dwarf_r0 + num;
14173
} else {
14174
// assert(0 && "Invalid register number");
14175
*success = false;
14176
return UINT32_MAX;
14177
}
14178
break;
14179
}
14180
14181
// Read our register.
14182
uint32_t val = ReadRegisterUnsigned(reg_kind, reg_num, 0, success);
14183
14184
// When executing an ARM instruction , PC reads as the address of the current
14185
// instruction plus 8. When executing a Thumb instruction , PC reads as the
14186
// address of the current instruction plus 4.
14187
if (num == 15) {
14188
if (CurrentInstrSet() == eModeARM)
14189
val += 8;
14190
else
14191
val += 4;
14192
}
14193
14194
return val;
14195
}
14196
14197
// Write the result to the ARM core register Rd, and optionally update the
14198
// condition flags based on the result.
14199
//
14200
// This helper method tries to encapsulate the following pseudocode from the
14201
// ARM Architecture Reference Manual:
14202
//
14203
// if d == 15 then // Can only occur for encoding A1
14204
// ALUWritePC(result); // setflags is always FALSE here
14205
// else
14206
// R[d] = result;
14207
// if setflags then
14208
// APSR.N = result<31>;
14209
// APSR.Z = IsZeroBit(result);
14210
// APSR.C = carry;
14211
// // APSR.V unchanged
14212
//
14213
// In the above case, the API client does not pass in the overflow arg, which
14214
// defaults to ~0u.
14215
bool EmulateInstructionARM::WriteCoreRegOptionalFlags(
14216
Context &context, const uint32_t result, const uint32_t Rd, bool setflags,
14217
const uint32_t carry, const uint32_t overflow) {
14218
if (Rd == 15) {
14219
if (!ALUWritePC(context, result))
14220
return false;
14221
} else {
14222
lldb::RegisterKind reg_kind;
14223
uint32_t reg_num;
14224
switch (Rd) {
14225
case SP_REG:
14226
reg_kind = eRegisterKindGeneric;
14227
reg_num = LLDB_REGNUM_GENERIC_SP;
14228
break;
14229
case LR_REG:
14230
reg_kind = eRegisterKindGeneric;
14231
reg_num = LLDB_REGNUM_GENERIC_RA;
14232
break;
14233
default:
14234
reg_kind = eRegisterKindDWARF;
14235
reg_num = dwarf_r0 + Rd;
14236
}
14237
if (!WriteRegisterUnsigned(context, reg_kind, reg_num, result))
14238
return false;
14239
if (setflags)
14240
return WriteFlags(context, result, carry, overflow);
14241
}
14242
return true;
14243
}
14244
14245
// This helper method tries to encapsulate the following pseudocode from the
14246
// ARM Architecture Reference Manual:
14247
//
14248
// APSR.N = result<31>;
14249
// APSR.Z = IsZeroBit(result);
14250
// APSR.C = carry;
14251
// APSR.V = overflow
14252
//
14253
// Default arguments can be specified for carry and overflow parameters, which
14254
// means not to update the respective flags.
14255
bool EmulateInstructionARM::WriteFlags(Context &context, const uint32_t result,
14256
const uint32_t carry,
14257
const uint32_t overflow) {
14258
m_new_inst_cpsr = m_opcode_cpsr;
14259
SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
14260
SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
14261
if (carry != ~0u)
14262
SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
14263
if (overflow != ~0u)
14264
SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
14265
if (m_new_inst_cpsr != m_opcode_cpsr) {
14266
if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
14267
LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
14268
return false;
14269
}
14270
return true;
14271
}
14272
14273
bool EmulateInstructionARM::EvaluateInstruction(uint32_t evaluate_options) {
14274
ARMOpcode *opcode_data = nullptr;
14275
14276
if (m_opcode_mode == eModeThumb)
14277
opcode_data =
14278
GetThumbOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa);
14279
else if (m_opcode_mode == eModeARM)
14280
opcode_data = GetARMOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa);
14281
14282
const bool auto_advance_pc =
14283
evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
14284
m_ignore_conditions =
14285
evaluate_options & eEmulateInstructionOptionIgnoreConditions;
14286
14287
bool success = false;
14288
if (m_opcode_cpsr == 0 || !m_ignore_conditions) {
14289
m_opcode_cpsr =
14290
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success);
14291
}
14292
14293
// Only return false if we are unable to read the CPSR if we care about
14294
// conditions
14295
if (!success && !m_ignore_conditions)
14296
return false;
14297
14298
uint32_t orig_pc_value = 0;
14299
if (auto_advance_pc) {
14300
orig_pc_value =
14301
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success);
14302
if (!success)
14303
return false;
14304
}
14305
14306
// Call the Emulate... function if we managed to decode the opcode.
14307
if (opcode_data) {
14308
success = (this->*opcode_data->callback)(m_opcode.GetOpcode32(),
14309
opcode_data->encoding);
14310
if (!success)
14311
return false;
14312
}
14313
14314
// Advance the ITSTATE bits to their values for the next instruction if we
14315
// haven't just executed an IT instruction what initialized it.
14316
if (m_opcode_mode == eModeThumb && m_it_session.InITBlock() &&
14317
(opcode_data == nullptr ||
14318
opcode_data->callback != &EmulateInstructionARM::EmulateIT))
14319
m_it_session.ITAdvance();
14320
14321
if (auto_advance_pc) {
14322
uint32_t after_pc_value =
14323
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success);
14324
if (!success)
14325
return false;
14326
14327
if (after_pc_value == orig_pc_value) {
14328
after_pc_value += m_opcode.GetByteSize();
14329
14330
EmulateInstruction::Context context;
14331
context.type = eContextAdvancePC;
14332
context.SetNoArgs();
14333
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc,
14334
after_pc_value))
14335
return false;
14336
}
14337
}
14338
return true;
14339
}
14340
14341
EmulateInstruction::InstructionCondition
14342
EmulateInstructionARM::GetInstructionCondition() {
14343
const uint32_t cond = CurrentCond(m_opcode.GetOpcode32());
14344
if (cond == 0xe || cond == 0xf || cond == UINT32_MAX)
14345
return EmulateInstruction::UnconditionalCondition;
14346
return cond;
14347
}
14348
14349
bool EmulateInstructionARM::TestEmulation(Stream &out_stream, ArchSpec &arch,
14350
OptionValueDictionary *test_data) {
14351
if (!test_data) {
14352
out_stream.Printf("TestEmulation: Missing test data.\n");
14353
return false;
14354
}
14355
14356
static constexpr llvm::StringLiteral opcode_key("opcode");
14357
static constexpr llvm::StringLiteral before_key("before_state");
14358
static constexpr llvm::StringLiteral after_key("after_state");
14359
14360
OptionValueSP value_sp = test_data->GetValueForKey(opcode_key);
14361
14362
uint32_t test_opcode;
14363
if ((value_sp.get() == nullptr) ||
14364
(value_sp->GetType() != OptionValue::eTypeUInt64)) {
14365
out_stream.Printf("TestEmulation: Error reading opcode from test file.\n");
14366
return false;
14367
}
14368
test_opcode = value_sp->GetValueAs<uint64_t>().value_or(0);
14369
14370
if (arch.GetTriple().getArch() == llvm::Triple::thumb ||
14371
arch.IsAlwaysThumbInstructions()) {
14372
m_opcode_mode = eModeThumb;
14373
if (test_opcode < 0x10000)
14374
m_opcode.SetOpcode16(test_opcode, endian::InlHostByteOrder());
14375
else
14376
m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder());
14377
} else if (arch.GetTriple().getArch() == llvm::Triple::arm) {
14378
m_opcode_mode = eModeARM;
14379
m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder());
14380
} else {
14381
out_stream.Printf("TestEmulation: Invalid arch.\n");
14382
return false;
14383
}
14384
14385
EmulationStateARM before_state;
14386
EmulationStateARM after_state;
14387
14388
value_sp = test_data->GetValueForKey(before_key);
14389
if ((value_sp.get() == nullptr) ||
14390
(value_sp->GetType() != OptionValue::eTypeDictionary)) {
14391
out_stream.Printf("TestEmulation: Failed to find 'before' state.\n");
14392
return false;
14393
}
14394
14395
OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary();
14396
if (!before_state.LoadStateFromDictionary(state_dictionary)) {
14397
out_stream.Printf("TestEmulation: Failed loading 'before' state.\n");
14398
return false;
14399
}
14400
14401
value_sp = test_data->GetValueForKey(after_key);
14402
if ((value_sp.get() == nullptr) ||
14403
(value_sp->GetType() != OptionValue::eTypeDictionary)) {
14404
out_stream.Printf("TestEmulation: Failed to find 'after' state.\n");
14405
return false;
14406
}
14407
14408
state_dictionary = value_sp->GetAsDictionary();
14409
if (!after_state.LoadStateFromDictionary(state_dictionary)) {
14410
out_stream.Printf("TestEmulation: Failed loading 'after' state.\n");
14411
return false;
14412
}
14413
14414
SetBaton((void *)&before_state);
14415
SetCallbacks(&EmulationStateARM::ReadPseudoMemory,
14416
&EmulationStateARM::WritePseudoMemory,
14417
&EmulationStateARM::ReadPseudoRegister,
14418
&EmulationStateARM::WritePseudoRegister);
14419
14420
bool success = EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC);
14421
if (!success) {
14422
out_stream.Printf("TestEmulation: EvaluateInstruction() failed.\n");
14423
return false;
14424
}
14425
14426
success = before_state.CompareState(after_state, out_stream);
14427
if (!success)
14428
out_stream.Printf("TestEmulation: State after emulation does not match "
14429
"'after' state.\n");
14430
14431
return success;
14432
}
14433
//
14434
//
14435
// const char *
14436
// EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)
14437
//{
14438
// if (reg_kind == eRegisterKindGeneric)
14439
// {
14440
// switch (reg_num)
14441
// {
14442
// case LLDB_REGNUM_GENERIC_PC: return "pc";
14443
// case LLDB_REGNUM_GENERIC_SP: return "sp";
14444
// case LLDB_REGNUM_GENERIC_FP: return "fp";
14445
// case LLDB_REGNUM_GENERIC_RA: return "lr";
14446
// case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";
14447
// default: return NULL;
14448
// }
14449
// }
14450
// else if (reg_kind == eRegisterKindDWARF)
14451
// {
14452
// return GetARMDWARFRegisterName (reg_num);
14453
// }
14454
// return NULL;
14455
//}
14456
//
14457
bool EmulateInstructionARM::CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) {
14458
unwind_plan.Clear();
14459
unwind_plan.SetRegisterKind(eRegisterKindDWARF);
14460
14461
UnwindPlan::RowSP row(new UnwindPlan::Row);
14462
14463
// Our previous Call Frame Address is the stack pointer
14464
row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp, 0);
14465
14466
unwind_plan.AppendRow(row);
14467
unwind_plan.SetSourceName("EmulateInstructionARM");
14468
unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
14469
unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
14470
unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
14471
unwind_plan.SetReturnAddressRegister(dwarf_lr);
14472
return true;
14473
}
14474
14475