1 //===-- EmulateInstructionARM.cpp -------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include <stdlib.h>
11
12 #include "EmulateInstructionARM.h"
13 #include "EmulationStateARM.h"
14 #include "lldb/Core/ArchSpec.h"
15 #include "lldb/Core/Address.h"
16 #include "lldb/Core/ConstString.h"
17 #include "lldb/Core/PluginManager.h"
18 #include "lldb/Core/Stream.h"
19 #include "lldb/Interpreter/OptionValueArray.h"
20 #include "lldb/Interpreter/OptionValueDictionary.h"
21 #include "lldb/Symbol/UnwindPlan.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/Support/MathExtras.h" // for SignExtend32 template function
28 // and countTrailingZeros function
29
30 using namespace lldb;
31 using namespace lldb_private;
32
33 // Convenient macro definitions.
34 #define APSR_C Bit32(m_opcode_cpsr, CPSR_C_POS)
35 #define APSR_V Bit32(m_opcode_cpsr, CPSR_V_POS)
36
37 #define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
38
39 //----------------------------------------------------------------------
40 //
41 // ITSession implementation
42 //
43 //----------------------------------------------------------------------
44
45 // A8.6.50
46 // Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
47 static uint32_t
CountITSize(uint32_t ITMask)48 CountITSize (uint32_t ITMask) {
49 // First count the trailing zeros of the IT mask.
50 uint32_t TZ = llvm::countTrailingZeros(ITMask);
51 if (TZ > 3)
52 {
53 #ifdef LLDB_CONFIGURATION_DEBUG
54 printf("Encoding error: IT Mask '0000'\n");
55 #endif
56 return 0;
57 }
58 return (4 - TZ);
59 }
60
61 // Init ITState. Note that at least one bit is always 1 in mask.
InitIT(uint32_t bits7_0)62 bool ITSession::InitIT(uint32_t bits7_0)
63 {
64 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
65 if (ITCounter == 0)
66 return false;
67
68 // A8.6.50 IT
69 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
70 if (FirstCond == 0xF)
71 {
72 #ifdef LLDB_CONFIGURATION_DEBUG
73 printf("Encoding error: IT FirstCond '1111'\n");
74 #endif
75 return false;
76 }
77 if (FirstCond == 0xE && ITCounter != 1)
78 {
79 #ifdef LLDB_CONFIGURATION_DEBUG
80 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
81 #endif
82 return false;
83 }
84
85 ITState = bits7_0;
86 return true;
87 }
88
89 // Update ITState if necessary.
ITAdvance()90 void ITSession::ITAdvance()
91 {
92 //assert(ITCounter);
93 --ITCounter;
94 if (ITCounter == 0)
95 ITState = 0;
96 else
97 {
98 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
99 SetBits32(ITState, 4, 0, NewITState4_0);
100 }
101 }
102
103 // Return true if we're inside an IT Block.
InITBlock()104 bool ITSession::InITBlock()
105 {
106 return ITCounter != 0;
107 }
108
109 // Return true if we're the last instruction inside an IT Block.
LastInITBlock()110 bool ITSession::LastInITBlock()
111 {
112 return ITCounter == 1;
113 }
114
115 // Get condition bits for the current thumb instruction.
GetCond()116 uint32_t ITSession::GetCond()
117 {
118 if (InITBlock())
119 return Bits32(ITState, 7, 4);
120 else
121 return COND_AL;
122 }
123
124 // ARM constants used during decoding
125 #define REG_RD 0
126 #define LDM_REGLIST 1
127 #define SP_REG 13
128 #define LR_REG 14
129 #define PC_REG 15
130 #define PC_REGLIST_BIT 0x8000
131
132 #define ARMv4 (1u << 0)
133 #define ARMv4T (1u << 1)
134 #define ARMv5T (1u << 2)
135 #define ARMv5TE (1u << 3)
136 #define ARMv5TEJ (1u << 4)
137 #define ARMv6 (1u << 5)
138 #define ARMv6K (1u << 6)
139 #define ARMv6T2 (1u << 7)
140 #define ARMv7 (1u << 8)
141 #define ARMv7S (1u << 9)
142 #define ARMv8 (1u << 10)
143 #define ARMvAll (0xffffffffu)
144
145 #define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv7S|ARMv8)
146 #define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv7S|ARMv8)
147 #define ARMV5TE_ABOVE (ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv7S|ARMv8)
148 #define ARMV5J_ABOVE (ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv7S|ARMv8)
149 #define ARMV6_ABOVE (ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv7S|ARMv8)
150 #define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv7S|ARMv8)
151 #define ARMV7_ABOVE (ARMv7|ARMv7S|ARMv8)
152
153 #define No_VFP 0
154 #define VFPv1 (1u << 1)
155 #define VFPv2 (1u << 2)
156 #define VFPv3 (1u << 3)
157 #define AdvancedSIMD (1u << 4)
158
159 #define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD)
160 #define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD)
161 #define VFPv2v3 (VFPv2 | VFPv3)
162
163 //----------------------------------------------------------------------
164 //
165 // EmulateInstructionARM implementation
166 //
167 //----------------------------------------------------------------------
168
169 void
Initialize()170 EmulateInstructionARM::Initialize ()
171 {
172 PluginManager::RegisterPlugin (GetPluginNameStatic (),
173 GetPluginDescriptionStatic (),
174 CreateInstance);
175 }
176
177 void
Terminate()178 EmulateInstructionARM::Terminate ()
179 {
180 PluginManager::UnregisterPlugin (CreateInstance);
181 }
182
183 ConstString
GetPluginNameStatic()184 EmulateInstructionARM::GetPluginNameStatic ()
185 {
186 static ConstString g_name("arm");
187 return g_name;
188 }
189
190 const char *
GetPluginDescriptionStatic()191 EmulateInstructionARM::GetPluginDescriptionStatic ()
192 {
193 return "Emulate instructions for the ARM architecture.";
194 }
195
196 EmulateInstruction *
CreateInstance(const ArchSpec & arch,InstructionType inst_type)197 EmulateInstructionARM::CreateInstance (const ArchSpec &arch, InstructionType inst_type)
198 {
199 if (EmulateInstructionARM::SupportsEmulatingInstructionsOfTypeStatic(inst_type))
200 {
201 if (arch.GetTriple().getArch() == llvm::Triple::arm)
202 {
203 std::unique_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
204
205 if (emulate_insn_ap.get())
206 return emulate_insn_ap.release();
207 }
208 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
209 {
210 std::unique_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
211
212 if (emulate_insn_ap.get())
213 return emulate_insn_ap.release();
214 }
215 }
216
217 return NULL;
218 }
219
220 bool
SetTargetTriple(const ArchSpec & arch)221 EmulateInstructionARM::SetTargetTriple (const ArchSpec &arch)
222 {
223 if (arch.GetTriple().getArch () == llvm::Triple::arm)
224 return true;
225 else if (arch.GetTriple().getArch () == llvm::Triple::thumb)
226 return true;
227
228 return false;
229 }
230
231 // Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
232 bool
WriteBits32UnknownToMemory(addr_t address)233 EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
234 {
235 EmulateInstruction::Context context;
236 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
237 context.SetNoArgs ();
238
239 uint32_t random_data = rand ();
240 const uint32_t addr_byte_size = GetAddressByteSize();
241
242 if (!MemAWrite (context, address, random_data, addr_byte_size))
243 return false;
244
245 return true;
246 }
247
248 // Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
249 bool
WriteBits32Unknown(int n)250 EmulateInstructionARM::WriteBits32Unknown (int n)
251 {
252 EmulateInstruction::Context context;
253 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
254 context.SetNoArgs ();
255
256 bool success;
257 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
258
259 if (!success)
260 return false;
261
262 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
263 return false;
264
265 return true;
266 }
267
268 bool
GetRegisterInfo(uint32_t reg_kind,uint32_t reg_num,RegisterInfo & reg_info)269 EmulateInstructionARM::GetRegisterInfo (uint32_t reg_kind, uint32_t reg_num, RegisterInfo ®_info)
270 {
271 if (reg_kind == eRegisterKindGeneric)
272 {
273 switch (reg_num)
274 {
275 case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = dwarf_pc; break;
276 case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_sp; break;
277 case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_r7; break;
278 case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = dwarf_lr; break;
279 case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = dwarf_cpsr; break;
280 default: return false;
281 }
282 }
283
284 if (reg_kind == eRegisterKindDWARF)
285 return GetARMDWARFRegisterInfo(reg_num, reg_info);
286 return false;
287 }
288
289 uint32_t
GetFramePointerRegisterNumber() const290 EmulateInstructionARM::GetFramePointerRegisterNumber () const
291 {
292 bool is_apple = false;
293 if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)
294 is_apple = true;
295 switch (m_arch.GetTriple().getOS())
296 {
297 case llvm::Triple::Darwin:
298 case llvm::Triple::MacOSX:
299 case llvm::Triple::IOS:
300 is_apple = true;
301 break;
302 default:
303 break;
304 }
305
306 /* On Apple iOS et al, the frame pointer register is always r7.
307 * Typically on other ARM systems, thumb code uses r7; arm code uses r11.
308 */
309
310 uint32_t fp_regnum = 11;
311
312 if (is_apple)
313 fp_regnum = 7;
314
315 if (m_opcode_mode == eModeThumb)
316 fp_regnum = 7;
317
318 return fp_regnum;
319 }
320
321 uint32_t
GetFramePointerDWARFRegisterNumber() const322 EmulateInstructionARM::GetFramePointerDWARFRegisterNumber () const
323 {
324 bool is_apple = false;
325 if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)
326 is_apple = true;
327 switch (m_arch.GetTriple().getOS())
328 {
329 case llvm::Triple::Darwin:
330 case llvm::Triple::MacOSX:
331 case llvm::Triple::IOS:
332 is_apple = true;
333 break;
334 default:
335 break;
336 }
337
338 /* On Apple iOS et al, the frame pointer register is always r7.
339 * Typically on other ARM systems, thumb code uses r7; arm code uses r11.
340 */
341
342 uint32_t fp_regnum = dwarf_r11;
343
344 if (is_apple)
345 fp_regnum = dwarf_r7;
346
347 if (m_opcode_mode == eModeThumb)
348 fp_regnum = dwarf_r7;
349
350 return fp_regnum;
351 }
352
353 // Push Multiple Registers stores multiple registers to the stack, storing to
354 // consecutive memory locations ending just below the address in SP, and updates
355 // SP to point to the start of the stored data.
356 bool
EmulatePUSH(const uint32_t opcode,const ARMEncoding encoding)357 EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding encoding)
358 {
359 #if 0
360 // ARM pseudo code...
361 if (ConditionPassed())
362 {
363 EncodingSpecificOperations();
364 NullCheckIfThumbEE(13);
365 address = SP - 4*BitCount(registers);
366
367 for (i = 0 to 14)
368 {
369 if (registers<i> == '1')
370 {
371 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
372 MemA[address,4] = bits(32) UNKNOWN;
373 else
374 MemA[address,4] = R[i];
375 address = address + 4;
376 }
377 }
378
379 if (registers<15> == '1') // Only possible for encoding A1 or A2
380 MemA[address,4] = PCStoreValue();
381
382 SP = SP - 4*BitCount(registers);
383 }
384 #endif
385
386 bool conditional = false;
387 bool success = false;
388 if (ConditionPassed(opcode, &conditional))
389 {
390 const uint32_t addr_byte_size = GetAddressByteSize();
391 const addr_t sp = ReadCoreReg (SP_REG, &success);
392 if (!success)
393 return false;
394 uint32_t registers = 0;
395 uint32_t Rt; // the source register
396 switch (encoding) {
397 case eEncodingT1:
398 registers = Bits32(opcode, 7, 0);
399 // The M bit represents LR.
400 if (Bit32(opcode, 8))
401 registers |= (1u << 14);
402 // if BitCount(registers) < 1 then UNPREDICTABLE;
403 if (BitCount(registers) < 1)
404 return false;
405 break;
406 case eEncodingT2:
407 // Ignore bits 15 & 13.
408 registers = Bits32(opcode, 15, 0) & ~0xa000;
409 // if BitCount(registers) < 2 then UNPREDICTABLE;
410 if (BitCount(registers) < 2)
411 return false;
412 break;
413 case eEncodingT3:
414 Rt = Bits32(opcode, 15, 12);
415 // if BadReg(t) then UNPREDICTABLE;
416 if (BadReg(Rt))
417 return false;
418 registers = (1u << Rt);
419 break;
420 case eEncodingA1:
421 registers = Bits32(opcode, 15, 0);
422 // Instead of return false, let's handle the following case as well,
423 // which amounts to pushing one reg onto the full descending stacks.
424 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
425 break;
426 case eEncodingA2:
427 Rt = Bits32(opcode, 15, 12);
428 // if t == 13 then UNPREDICTABLE;
429 if (Rt == dwarf_sp)
430 return false;
431 registers = (1u << Rt);
432 break;
433 default:
434 return false;
435 }
436 addr_t sp_offset = addr_byte_size * BitCount (registers);
437 addr_t addr = sp - sp_offset;
438 uint32_t i;
439
440 EmulateInstruction::Context context;
441 if (conditional)
442 context.type = EmulateInstruction::eContextRegisterStore;
443 else
444 context.type = EmulateInstruction::eContextPushRegisterOnStack;
445 RegisterInfo reg_info;
446 RegisterInfo sp_reg;
447 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
448 for (i=0; i<15; ++i)
449 {
450 if (BitIsSet (registers, i))
451 {
452 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, reg_info);
453 context.SetRegisterToRegisterPlusOffset (reg_info, sp_reg, addr - sp);
454 uint32_t reg_value = ReadCoreReg(i, &success);
455 if (!success)
456 return false;
457 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
458 return false;
459 addr += addr_byte_size;
460 }
461 }
462
463 if (BitIsSet (registers, 15))
464 {
465 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, reg_info);
466 context.SetRegisterToRegisterPlusOffset (reg_info, sp_reg, addr - sp);
467 const uint32_t pc = ReadCoreReg(PC_REG, &success);
468 if (!success)
469 return false;
470 if (!MemAWrite (context, addr, pc, addr_byte_size))
471 return false;
472 }
473
474 context.type = EmulateInstruction::eContextAdjustStackPointer;
475 context.SetImmediateSigned (-sp_offset);
476
477 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
478 return false;
479 }
480 return true;
481 }
482
483 // Pop Multiple Registers loads multiple registers from the stack, loading from
484 // consecutive memory locations staring at the address in SP, and updates
485 // SP to point just above the loaded data.
486 bool
EmulatePOP(const uint32_t opcode,const ARMEncoding encoding)487 EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding encoding)
488 {
489 #if 0
490 // ARM pseudo code...
491 if (ConditionPassed())
492 {
493 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
494 address = SP;
495 for i = 0 to 14
496 if registers<i> == '1' then
497 R[i] = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
498 if registers<15> == '1' then
499 if UnalignedAllowed then
500 LoadWritePC(MemU[address,4]);
501 else
502 LoadWritePC(MemA[address,4]);
503 if registers<13> == '0' then SP = SP + 4*BitCount(registers);
504 if registers<13> == '1' then SP = bits(32) UNKNOWN;
505 }
506 #endif
507
508 bool success = false;
509
510 bool conditional = false;
511 if (ConditionPassed(opcode, &conditional))
512 {
513 const uint32_t addr_byte_size = GetAddressByteSize();
514 const addr_t sp = ReadCoreReg (SP_REG, &success);
515 if (!success)
516 return false;
517 uint32_t registers = 0;
518 uint32_t Rt; // the destination register
519 switch (encoding) {
520 case eEncodingT1:
521 registers = Bits32(opcode, 7, 0);
522 // The P bit represents PC.
523 if (Bit32(opcode, 8))
524 registers |= (1u << 15);
525 // if BitCount(registers) < 1 then UNPREDICTABLE;
526 if (BitCount(registers) < 1)
527 return false;
528 break;
529 case eEncodingT2:
530 // Ignore bit 13.
531 registers = Bits32(opcode, 15, 0) & ~0x2000;
532 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
533 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
534 return false;
535 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
536 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
537 return false;
538 break;
539 case eEncodingT3:
540 Rt = Bits32(opcode, 15, 12);
541 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
542 if (Rt == 13)
543 return false;
544 if (Rt == 15 && InITBlock() && !LastInITBlock())
545 return false;
546 registers = (1u << Rt);
547 break;
548 case eEncodingA1:
549 registers = Bits32(opcode, 15, 0);
550 // Instead of return false, let's handle the following case as well,
551 // which amounts to popping one reg from the full descending stacks.
552 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
553
554 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
555 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
556 return false;
557 break;
558 case eEncodingA2:
559 Rt = Bits32(opcode, 15, 12);
560 // if t == 13 then UNPREDICTABLE;
561 if (Rt == dwarf_sp)
562 return false;
563 registers = (1u << Rt);
564 break;
565 default:
566 return false;
567 }
568 addr_t sp_offset = addr_byte_size * BitCount (registers);
569 addr_t addr = sp;
570 uint32_t i, data;
571
572 EmulateInstruction::Context context;
573 if (conditional)
574 context.type = EmulateInstruction::eContextRegisterLoad;
575 else
576 context.type = EmulateInstruction::eContextPopRegisterOffStack;
577
578 RegisterInfo sp_reg;
579 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
580
581 for (i=0; i<15; ++i)
582 {
583 if (BitIsSet (registers, i))
584 {
585 context.SetRegisterPlusOffset (sp_reg, addr - sp);
586 data = MemARead(context, addr, 4, 0, &success);
587 if (!success)
588 return false;
589 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, data))
590 return false;
591 addr += addr_byte_size;
592 }
593 }
594
595 if (BitIsSet (registers, 15))
596 {
597 context.SetRegisterPlusOffset (sp_reg, addr - sp);
598 data = MemARead(context, addr, 4, 0, &success);
599 if (!success)
600 return false;
601 // In ARMv5T and above, this is an interworking branch.
602 if (!LoadWritePC(context, data))
603 return false;
604 //addr += addr_byte_size;
605 }
606
607 context.type = EmulateInstruction::eContextAdjustStackPointer;
608 context.SetImmediateSigned (sp_offset);
609
610 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
611 return false;
612 }
613 return true;
614 }
615
616 // Set r7 or ip to point to saved value residing within the stack.
617 // ADD (SP plus immediate)
618 bool
EmulateADDRdSPImm(const uint32_t opcode,const ARMEncoding encoding)619 EmulateInstructionARM::EmulateADDRdSPImm (const uint32_t opcode, const ARMEncoding encoding)
620 {
621 #if 0
622 // ARM pseudo code...
623 if (ConditionPassed())
624 {
625 EncodingSpecificOperations();
626 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
627 if d == 15 then
628 ALUWritePC(result); // setflags is always FALSE here
629 else
630 R[d] = result;
631 if setflags then
632 APSR.N = result<31>;
633 APSR.Z = IsZeroBit(result);
634 APSR.C = carry;
635 APSR.V = overflow;
636 }
637 #endif
638
639 bool success = false;
640
641 if (ConditionPassed(opcode))
642 {
643 const addr_t sp = ReadCoreReg (SP_REG, &success);
644 if (!success)
645 return false;
646 uint32_t Rd; // the destination register
647 uint32_t imm32;
648 switch (encoding) {
649 case eEncodingT1:
650 Rd = 7;
651 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
652 break;
653 case eEncodingA1:
654 Rd = Bits32(opcode, 15, 12);
655 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
656 break;
657 default:
658 return false;
659 }
660 addr_t sp_offset = imm32;
661 addr_t addr = sp + sp_offset; // a pointer to the stack area
662
663 EmulateInstruction::Context context;
664 context.type = eContextSetFramePointer;
665 RegisterInfo sp_reg;
666 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
667 context.SetRegisterPlusOffset (sp_reg, sp_offset);
668
669 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
670 return false;
671 }
672 return true;
673 }
674
675 // Set r7 or ip to the current stack pointer.
676 // MOV (register)
677 bool
EmulateMOVRdSP(const uint32_t opcode,const ARMEncoding encoding)678 EmulateInstructionARM::EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding encoding)
679 {
680 #if 0
681 // ARM pseudo code...
682 if (ConditionPassed())
683 {
684 EncodingSpecificOperations();
685 result = R[m];
686 if d == 15 then
687 ALUWritePC(result); // setflags is always FALSE here
688 else
689 R[d] = result;
690 if setflags then
691 APSR.N = result<31>;
692 APSR.Z = IsZeroBit(result);
693 // APSR.C unchanged
694 // APSR.V unchanged
695 }
696 #endif
697
698 bool success = false;
699
700 if (ConditionPassed(opcode))
701 {
702 const addr_t sp = ReadCoreReg (SP_REG, &success);
703 if (!success)
704 return false;
705 uint32_t Rd; // the destination register
706 switch (encoding) {
707 case eEncodingT1:
708 Rd = 7;
709 break;
710 case eEncodingA1:
711 Rd = 12;
712 break;
713 default:
714 return false;
715 }
716
717 EmulateInstruction::Context context;
718 if (Rd == GetFramePointerRegisterNumber())
719 context.type = EmulateInstruction::eContextSetFramePointer;
720 else
721 context.type = EmulateInstruction::eContextRegisterPlusOffset;
722 RegisterInfo sp_reg;
723 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
724 context.SetRegisterPlusOffset (sp_reg, 0);
725
726 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
727 return false;
728 }
729 return true;
730 }
731
732 // Move from high register (r8-r15) to low register (r0-r7).
733 // MOV (register)
734 bool
EmulateMOVLowHigh(const uint32_t opcode,const ARMEncoding encoding)735 EmulateInstructionARM::EmulateMOVLowHigh (const uint32_t opcode, const ARMEncoding encoding)
736 {
737 return EmulateMOVRdRm (opcode, encoding);
738 }
739
740 // Move from register to register.
741 // MOV (register)
742 bool
EmulateMOVRdRm(const uint32_t opcode,const ARMEncoding encoding)743 EmulateInstructionARM::EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding encoding)
744 {
745 #if 0
746 // ARM pseudo code...
747 if (ConditionPassed())
748 {
749 EncodingSpecificOperations();
750 result = R[m];
751 if d == 15 then
752 ALUWritePC(result); // setflags is always FALSE here
753 else
754 R[d] = result;
755 if setflags then
756 APSR.N = result<31>;
757 APSR.Z = IsZeroBit(result);
758 // APSR.C unchanged
759 // APSR.V unchanged
760 }
761 #endif
762
763 bool success = false;
764
765 if (ConditionPassed(opcode))
766 {
767 uint32_t Rm; // the source register
768 uint32_t Rd; // the destination register
769 bool setflags;
770 switch (encoding) {
771 case eEncodingT1:
772 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
773 Rm = Bits32(opcode, 6, 3);
774 setflags = false;
775 if (Rd == 15 && InITBlock() && !LastInITBlock())
776 return false;
777 break;
778 case eEncodingT2:
779 Rd = Bits32(opcode, 2, 0);
780 Rm = Bits32(opcode, 5, 3);
781 setflags = true;
782 if (InITBlock())
783 return false;
784 break;
785 case eEncodingT3:
786 Rd = Bits32(opcode, 11, 8);
787 Rm = Bits32(opcode, 3, 0);
788 setflags = BitIsSet(opcode, 20);
789 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
790 if (setflags && (BadReg(Rd) || BadReg(Rm)))
791 return false;
792 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
793 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
794 return false;
795 break;
796 case eEncodingA1:
797 Rd = Bits32(opcode, 15, 12);
798 Rm = Bits32(opcode, 3, 0);
799 setflags = BitIsSet(opcode, 20);
800
801 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
802 if (Rd == 15 && setflags)
803 return EmulateSUBSPcLrEtc (opcode, encoding);
804 break;
805 default:
806 return false;
807 }
808 uint32_t result = ReadCoreReg(Rm, &success);
809 if (!success)
810 return false;
811
812 // The context specifies that Rm is to be moved into Rd.
813 EmulateInstruction::Context context;
814 context.type = EmulateInstruction::eContextRegisterLoad;
815 RegisterInfo dwarf_reg;
816 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
817 context.SetRegister (dwarf_reg);
818
819 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
820 return false;
821 }
822 return true;
823 }
824
825 // Move (immediate) writes an immediate value to the destination register. It
826 // can optionally update the condition flags based on the value.
827 // MOV (immediate)
828 bool
EmulateMOVRdImm(const uint32_t opcode,const ARMEncoding encoding)829 EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding encoding)
830 {
831 #if 0
832 // ARM pseudo code...
833 if (ConditionPassed())
834 {
835 EncodingSpecificOperations();
836 result = imm32;
837 if d == 15 then // Can only occur for ARM encoding
838 ALUWritePC(result); // setflags is always FALSE here
839 else
840 R[d] = result;
841 if setflags then
842 APSR.N = result<31>;
843 APSR.Z = IsZeroBit(result);
844 APSR.C = carry;
845 // APSR.V unchanged
846 }
847 #endif
848
849 if (ConditionPassed(opcode))
850 {
851 uint32_t Rd; // the destination register
852 uint32_t imm32; // the immediate value to be written to Rd
853 uint32_t carry = 0; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
854 // for setflags == false, this value is a don't care
855 // initialized to 0 to silence the static analyzer
856 bool setflags;
857 switch (encoding) {
858 case eEncodingT1:
859 Rd = Bits32(opcode, 10, 8);
860 setflags = !InITBlock();
861 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
862 carry = APSR_C;
863
864 break;
865
866 case eEncodingT2:
867 Rd = Bits32(opcode, 11, 8);
868 setflags = BitIsSet(opcode, 20);
869 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
870 if (BadReg(Rd))
871 return false;
872
873 break;
874
875 case eEncodingT3:
876 {
877 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, 32);
878 Rd = Bits32 (opcode, 11, 8);
879 setflags = false;
880 uint32_t imm4 = Bits32 (opcode, 19, 16);
881 uint32_t imm3 = Bits32 (opcode, 14, 12);
882 uint32_t i = Bit32 (opcode, 26);
883 uint32_t imm8 = Bits32 (opcode, 7, 0);
884 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
885
886 // if BadReg(d) then UNPREDICTABLE;
887 if (BadReg (Rd))
888 return false;
889 }
890 break;
891
892 case eEncodingA1:
893 // d = UInt(Rd); setflags = (S == �1�); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C);
894 Rd = Bits32 (opcode, 15, 12);
895 setflags = BitIsSet (opcode, 20);
896 imm32 = ARMExpandImm_C (opcode, APSR_C, carry);
897
898 // if Rd == �1111� && S == �1� then SEE SUBS PC, LR and related instructions;
899 if ((Rd == 15) && setflags)
900 return EmulateSUBSPcLrEtc (opcode, encoding);
901
902 break;
903
904 case eEncodingA2:
905 {
906 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
907 Rd = Bits32 (opcode, 15, 12);
908 setflags = false;
909 uint32_t imm4 = Bits32 (opcode, 19, 16);
910 uint32_t imm12 = Bits32 (opcode, 11, 0);
911 imm32 = (imm4 << 12) | imm12;
912
913 // if d == 15 then UNPREDICTABLE;
914 if (Rd == 15)
915 return false;
916 }
917 break;
918
919 default:
920 return false;
921 }
922 uint32_t result = imm32;
923
924 // The context specifies that an immediate is to be moved into Rd.
925 EmulateInstruction::Context context;
926 context.type = EmulateInstruction::eContextImmediate;
927 context.SetNoArgs ();
928
929 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
930 return false;
931 }
932 return true;
933 }
934
935 // MUL multiplies two register values. The least significant 32 bits of the result are written to the destination
936 // register. These 32 bits do not depend on whether the source register values are considered to be signed values or
937 // unsigned values.
938 //
939 // Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is
940 // limited to only a few forms of the instruction.
941 bool
EmulateMUL(const uint32_t opcode,const ARMEncoding encoding)942 EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding)
943 {
944 #if 0
945 if ConditionPassed() then
946 EncodingSpecificOperations();
947 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
948 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
949 result = operand1 * operand2;
950 R[d] = result<31:0>;
951 if setflags then
952 APSR.N = result<31>;
953 APSR.Z = IsZeroBit(result);
954 if ArchVersion() == 4 then
955 APSR.C = bit UNKNOWN;
956 // else APSR.C unchanged
957 // APSR.V always unchanged
958 #endif
959
960 if (ConditionPassed(opcode))
961 {
962 uint32_t d;
963 uint32_t n;
964 uint32_t m;
965 bool setflags;
966
967 // EncodingSpecificOperations();
968 switch (encoding)
969 {
970 case eEncodingT1:
971 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
972 d = Bits32 (opcode, 2, 0);
973 n = Bits32 (opcode, 5, 3);
974 m = Bits32 (opcode, 2, 0);
975 setflags = !InITBlock();
976
977 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
978 if ((ArchVersion() < ARMv6) && (d == n))
979 return false;
980
981 break;
982
983 case eEncodingT2:
984 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
985 d = Bits32 (opcode, 11, 8);
986 n = Bits32 (opcode, 19, 16);
987 m = Bits32 (opcode, 3, 0);
988 setflags = false;
989
990 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
991 if (BadReg (d) || BadReg (n) || BadReg (m))
992 return false;
993
994 break;
995
996 case eEncodingA1:
997 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
998 d = Bits32 (opcode, 19, 16);
999 n = Bits32 (opcode, 3, 0);
1000 m = Bits32 (opcode, 11, 8);
1001 setflags = BitIsSet (opcode, 20);
1002
1003 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
1004 if ((d == 15) || (n == 15) || (m == 15))
1005 return false;
1006
1007 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
1008 if ((ArchVersion() < ARMv6) && (d == n))
1009 return false;
1010
1011 break;
1012
1013 default:
1014 return false;
1015 }
1016
1017 bool success = false;
1018
1019 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
1020 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1021 if (!success)
1022 return false;
1023
1024 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
1025 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
1026 if (!success)
1027 return false;
1028
1029 // result = operand1 * operand2;
1030 uint64_t result = operand1 * operand2;
1031
1032 // R[d] = result<31:0>;
1033 RegisterInfo op1_reg;
1034 RegisterInfo op2_reg;
1035 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, op1_reg);
1036 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, op2_reg);
1037
1038 EmulateInstruction::Context context;
1039 context.type = eContextArithmetic;
1040 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
1041
1042 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
1043 return false;
1044
1045 // if setflags then
1046 if (setflags)
1047 {
1048 // APSR.N = result<31>;
1049 // APSR.Z = IsZeroBit(result);
1050 m_new_inst_cpsr = m_opcode_cpsr;
1051 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
1052 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
1053 if (m_new_inst_cpsr != m_opcode_cpsr)
1054 {
1055 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
1056 return false;
1057 }
1058
1059 // if ArchVersion() == 4 then
1060 // APSR.C = bit UNKNOWN;
1061 }
1062 }
1063 return true;
1064 }
1065
1066 // Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
1067 // It can optionally update the condition flags based on the value.
1068 bool
EmulateMVNImm(const uint32_t opcode,const ARMEncoding encoding)1069 EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding)
1070 {
1071 #if 0
1072 // ARM pseudo code...
1073 if (ConditionPassed())
1074 {
1075 EncodingSpecificOperations();
1076 result = NOT(imm32);
1077 if d == 15 then // Can only occur for ARM encoding
1078 ALUWritePC(result); // setflags is always FALSE here
1079 else
1080 R[d] = result;
1081 if setflags then
1082 APSR.N = result<31>;
1083 APSR.Z = IsZeroBit(result);
1084 APSR.C = carry;
1085 // APSR.V unchanged
1086 }
1087 #endif
1088
1089 if (ConditionPassed(opcode))
1090 {
1091 uint32_t Rd; // the destination register
1092 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
1093 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
1094 bool setflags;
1095 switch (encoding) {
1096 case eEncodingT1:
1097 Rd = Bits32(opcode, 11, 8);
1098 setflags = BitIsSet(opcode, 20);
1099 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
1100 break;
1101 case eEncodingA1:
1102 Rd = Bits32(opcode, 15, 12);
1103 setflags = BitIsSet(opcode, 20);
1104 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
1105
1106 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
1107 if (Rd == 15 && setflags)
1108 return EmulateSUBSPcLrEtc (opcode, encoding);
1109 break;
1110 default:
1111 return false;
1112 }
1113 uint32_t result = ~imm32;
1114
1115 // The context specifies that an immediate is to be moved into Rd.
1116 EmulateInstruction::Context context;
1117 context.type = EmulateInstruction::eContextImmediate;
1118 context.SetNoArgs ();
1119
1120 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1121 return false;
1122 }
1123 return true;
1124 }
1125
1126 // Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
1127 // It can optionally update the condition flags based on the result.
1128 bool
EmulateMVNReg(const uint32_t opcode,const ARMEncoding encoding)1129 EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding)
1130 {
1131 #if 0
1132 // ARM pseudo code...
1133 if (ConditionPassed())
1134 {
1135 EncodingSpecificOperations();
1136 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
1137 result = NOT(shifted);
1138 if d == 15 then // Can only occur for ARM encoding
1139 ALUWritePC(result); // setflags is always FALSE here
1140 else
1141 R[d] = result;
1142 if setflags then
1143 APSR.N = result<31>;
1144 APSR.Z = IsZeroBit(result);
1145 APSR.C = carry;
1146 // APSR.V unchanged
1147 }
1148 #endif
1149
1150 if (ConditionPassed(opcode))
1151 {
1152 uint32_t Rm; // the source register
1153 uint32_t Rd; // the destination register
1154 ARM_ShifterType shift_t;
1155 uint32_t shift_n; // the shift applied to the value read from Rm
1156 bool setflags;
1157 uint32_t carry; // the carry bit after the shift operation
1158 switch (encoding) {
1159 case eEncodingT1:
1160 Rd = Bits32(opcode, 2, 0);
1161 Rm = Bits32(opcode, 5, 3);
1162 setflags = !InITBlock();
1163 shift_t = SRType_LSL;
1164 shift_n = 0;
1165 if (InITBlock())
1166 return false;
1167 break;
1168 case eEncodingT2:
1169 Rd = Bits32(opcode, 11, 8);
1170 Rm = Bits32(opcode, 3, 0);
1171 setflags = BitIsSet(opcode, 20);
1172 shift_n = DecodeImmShiftThumb(opcode, shift_t);
1173 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
1174 if (BadReg(Rd) || BadReg(Rm))
1175 return false;
1176 break;
1177 case eEncodingA1:
1178 Rd = Bits32(opcode, 15, 12);
1179 Rm = Bits32(opcode, 3, 0);
1180 setflags = BitIsSet(opcode, 20);
1181 shift_n = DecodeImmShiftARM(opcode, shift_t);
1182 break;
1183 default:
1184 return false;
1185 }
1186 bool success = false;
1187 uint32_t value = ReadCoreReg(Rm, &success);
1188 if (!success)
1189 return false;
1190
1191 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry, &success);
1192 if (!success)
1193 return false;
1194 uint32_t result = ~shifted;
1195
1196 // The context specifies that an immediate is to be moved into Rd.
1197 EmulateInstruction::Context context;
1198 context.type = EmulateInstruction::eContextImmediate;
1199 context.SetNoArgs ();
1200
1201 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1202 return false;
1203 }
1204 return true;
1205 }
1206
1207 // PC relative immediate load into register, possibly followed by ADD (SP plus register).
1208 // LDR (literal)
1209 bool
EmulateLDRRtPCRelative(const uint32_t opcode,const ARMEncoding encoding)1210 EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding)
1211 {
1212 #if 0
1213 // ARM pseudo code...
1214 if (ConditionPassed())
1215 {
1216 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1217 base = Align(PC,4);
1218 address = if add then (base + imm32) else (base - imm32);
1219 data = MemU[address,4];
1220 if t == 15 then
1221 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1222 elsif UnalignedSupport() || address<1:0> = '00' then
1223 R[t] = data;
1224 else // Can only apply before ARMv7
1225 if CurrentInstrSet() == InstrSet_ARM then
1226 R[t] = ROR(data, 8*UInt(address<1:0>));
1227 else
1228 R[t] = bits(32) UNKNOWN;
1229 }
1230 #endif
1231
1232 if (ConditionPassed(opcode))
1233 {
1234 bool success = false;
1235 const uint32_t pc = ReadCoreReg(PC_REG, &success);
1236 if (!success)
1237 return false;
1238
1239 // PC relative immediate load context
1240 EmulateInstruction::Context context;
1241 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1242 RegisterInfo pc_reg;
1243 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
1244 context.SetRegisterPlusOffset (pc_reg, 0);
1245
1246 uint32_t Rt; // the destination register
1247 uint32_t imm32; // immediate offset from the PC
1248 bool add; // +imm32 or -imm32?
1249 addr_t base; // the base address
1250 addr_t address; // the PC relative address
1251 uint32_t data; // the literal data value from the PC relative load
1252 switch (encoding) {
1253 case eEncodingT1:
1254 Rt = Bits32(opcode, 10, 8);
1255 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
1256 add = true;
1257 break;
1258 case eEncodingT2:
1259 Rt = Bits32(opcode, 15, 12);
1260 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1261 add = BitIsSet(opcode, 23);
1262 if (Rt == 15 && InITBlock() && !LastInITBlock())
1263 return false;
1264 break;
1265 default:
1266 return false;
1267 }
1268
1269 base = Align(pc, 4);
1270 if (add)
1271 address = base + imm32;
1272 else
1273 address = base - imm32;
1274
1275 context.SetRegisterPlusOffset(pc_reg, address - base);
1276 data = MemURead(context, address, 4, 0, &success);
1277 if (!success)
1278 return false;
1279
1280 if (Rt == 15)
1281 {
1282 if (Bits32(address, 1, 0) == 0)
1283 {
1284 // In ARMv5T and above, this is an interworking branch.
1285 if (!LoadWritePC(context, data))
1286 return false;
1287 }
1288 else
1289 return false;
1290 }
1291 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1292 {
1293 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1294 return false;
1295 }
1296 else // We don't handle ARM for now.
1297 return false;
1298
1299 }
1300 return true;
1301 }
1302
1303 // An add operation to adjust the SP.
1304 // ADD (SP plus immediate)
1305 bool
EmulateADDSPImm(const uint32_t opcode,const ARMEncoding encoding)1306 EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding)
1307 {
1308 #if 0
1309 // ARM pseudo code...
1310 if (ConditionPassed())
1311 {
1312 EncodingSpecificOperations();
1313 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
1314 if d == 15 then // Can only occur for ARM encoding
1315 ALUWritePC(result); // setflags is always FALSE here
1316 else
1317 R[d] = result;
1318 if setflags then
1319 APSR.N = result<31>;
1320 APSR.Z = IsZeroBit(result);
1321 APSR.C = carry;
1322 APSR.V = overflow;
1323 }
1324 #endif
1325
1326 bool success = false;
1327
1328 if (ConditionPassed(opcode))
1329 {
1330 const addr_t sp = ReadCoreReg (SP_REG, &success);
1331 if (!success)
1332 return false;
1333 uint32_t imm32; // the immediate operand
1334 uint32_t d;
1335 //bool setflags = false; // Add this back if/when support eEncodingT3 eEncodingA1
1336 switch (encoding)
1337 {
1338 case eEncodingT1:
1339 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
1340 d = Bits32 (opcode, 10, 8);
1341 imm32 = (Bits32 (opcode, 7, 0) << 2);
1342
1343 break;
1344
1345 case eEncodingT2:
1346 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
1347 d = 13;
1348 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1349
1350 break;
1351
1352 default:
1353 return false;
1354 }
1355 addr_t sp_offset = imm32;
1356 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1357
1358 EmulateInstruction::Context context;
1359 context.type = EmulateInstruction::eContextAdjustStackPointer;
1360 RegisterInfo sp_reg;
1361 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
1362 context.SetRegisterPlusOffset (sp_reg, sp_offset);
1363
1364 if (d == 15)
1365 {
1366 if (!ALUWritePC (context, addr))
1367 return false;
1368 }
1369 else
1370 {
1371 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr))
1372 return false;
1373
1374 // Add this back if/when support eEncodingT3 eEncodingA1
1375 //if (setflags)
1376 //{
1377 // APSR.N = result<31>;
1378 // APSR.Z = IsZeroBit(result);
1379 // APSR.C = carry;
1380 // APSR.V = overflow;
1381 //}
1382 }
1383 }
1384 return true;
1385 }
1386
1387 // An add operation to adjust the SP.
1388 // ADD (SP plus register)
1389 bool
EmulateADDSPRm(const uint32_t opcode,const ARMEncoding encoding)1390 EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding)
1391 {
1392 #if 0
1393 // ARM pseudo code...
1394 if (ConditionPassed())
1395 {
1396 EncodingSpecificOperations();
1397 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1398 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
1399 if d == 15 then
1400 ALUWritePC(result); // setflags is always FALSE here
1401 else
1402 R[d] = result;
1403 if setflags then
1404 APSR.N = result<31>;
1405 APSR.Z = IsZeroBit(result);
1406 APSR.C = carry;
1407 APSR.V = overflow;
1408 }
1409 #endif
1410
1411 bool success = false;
1412
1413 if (ConditionPassed(opcode))
1414 {
1415 const addr_t sp = ReadCoreReg (SP_REG, &success);
1416 if (!success)
1417 return false;
1418 uint32_t Rm; // the second operand
1419 switch (encoding) {
1420 case eEncodingT2:
1421 Rm = Bits32(opcode, 6, 3);
1422 break;
1423 default:
1424 return false;
1425 }
1426 int32_t reg_value = ReadCoreReg(Rm, &success);
1427 if (!success)
1428 return false;
1429
1430 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1431
1432 EmulateInstruction::Context context;
1433 context.type = eContextArithmetic;
1434 RegisterInfo sp_reg;
1435 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
1436
1437 RegisterInfo other_reg;
1438 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, other_reg);
1439 context.SetRegisterRegisterOperands (sp_reg, other_reg);
1440
1441 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
1442 return false;
1443 }
1444 return true;
1445 }
1446
1447 // Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1448 // at a PC-relative address, and changes instruction set from ARM to Thumb, or
1449 // from Thumb to ARM.
1450 // BLX (immediate)
1451 bool
EmulateBLXImmediate(const uint32_t opcode,const ARMEncoding encoding)1452 EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding)
1453 {
1454 #if 0
1455 // ARM pseudo code...
1456 if (ConditionPassed())
1457 {
1458 EncodingSpecificOperations();
1459 if CurrentInstrSet() == InstrSet_ARM then
1460 LR = PC - 4;
1461 else
1462 LR = PC<31:1> : '1';
1463 if targetInstrSet == InstrSet_ARM then
1464 targetAddress = Align(PC,4) + imm32;
1465 else
1466 targetAddress = PC + imm32;
1467 SelectInstrSet(targetInstrSet);
1468 BranchWritePC(targetAddress);
1469 }
1470 #endif
1471
1472 bool success = true;
1473
1474 if (ConditionPassed(opcode))
1475 {
1476 EmulateInstruction::Context context;
1477 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
1478 const uint32_t pc = ReadCoreReg(PC_REG, &success);
1479 if (!success)
1480 return false;
1481 addr_t lr; // next instruction address
1482 addr_t target; // target address
1483 int32_t imm32; // PC-relative offset
1484 switch (encoding) {
1485 case eEncodingT1:
1486 {
1487 lr = pc | 1u; // return address
1488 uint32_t S = Bit32(opcode, 26);
1489 uint32_t imm10 = Bits32(opcode, 25, 16);
1490 uint32_t J1 = Bit32(opcode, 13);
1491 uint32_t J2 = Bit32(opcode, 11);
1492 uint32_t imm11 = Bits32(opcode, 10, 0);
1493 uint32_t I1 = !(J1 ^ S);
1494 uint32_t I2 = !(J2 ^ S);
1495 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
1496 imm32 = llvm::SignExtend32<25>(imm25);
1497 target = pc + imm32;
1498 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
1499 if (InITBlock() && !LastInITBlock())
1500 return false;
1501 break;
1502 }
1503 case eEncodingT2:
1504 {
1505 lr = pc | 1u; // return address
1506 uint32_t S = Bit32(opcode, 26);
1507 uint32_t imm10H = Bits32(opcode, 25, 16);
1508 uint32_t J1 = Bit32(opcode, 13);
1509 uint32_t J2 = Bit32(opcode, 11);
1510 uint32_t imm10L = Bits32(opcode, 10, 1);
1511 uint32_t I1 = !(J1 ^ S);
1512 uint32_t I2 = !(J2 ^ S);
1513 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
1514 imm32 = llvm::SignExtend32<25>(imm25);
1515 target = Align(pc, 4) + imm32;
1516 context.SetISAAndImmediateSigned (eModeARM, 4 + imm32);
1517 if (InITBlock() && !LastInITBlock())
1518 return false;
1519 break;
1520 }
1521 case eEncodingA1:
1522 lr = pc - 4; // return address
1523 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1524 target = Align(pc, 4) + imm32;
1525 context.SetISAAndImmediateSigned (eModeARM, 8 + imm32);
1526 break;
1527 case eEncodingA2:
1528 lr = pc - 4; // return address
1529 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
1530 target = pc + imm32;
1531 context.SetISAAndImmediateSigned (eModeThumb, 8 + imm32);
1532 break;
1533 default:
1534 return false;
1535 }
1536 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1537 return false;
1538 if (!BranchWritePC(context, target))
1539 return false;
1540 }
1541 return true;
1542 }
1543
1544 // Branch with Link and Exchange (register) calls a subroutine at an address and
1545 // instruction set specified by a register.
1546 // BLX (register)
1547 bool
EmulateBLXRm(const uint32_t opcode,const ARMEncoding encoding)1548 EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding)
1549 {
1550 #if 0
1551 // ARM pseudo code...
1552 if (ConditionPassed())
1553 {
1554 EncodingSpecificOperations();
1555 target = R[m];
1556 if CurrentInstrSet() == InstrSet_ARM then
1557 next_instr_addr = PC - 4;
1558 LR = next_instr_addr;
1559 else
1560 next_instr_addr = PC - 2;
1561 LR = next_instr_addr<31:1> : '1';
1562 BXWritePC(target);
1563 }
1564 #endif
1565
1566 bool success = false;
1567
1568 if (ConditionPassed(opcode))
1569 {
1570 EmulateInstruction::Context context;
1571 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1572 const uint32_t pc = ReadCoreReg(PC_REG, &success);
1573 addr_t lr; // next instruction address
1574 if (!success)
1575 return false;
1576 uint32_t Rm; // the register with the target address
1577 switch (encoding) {
1578 case eEncodingT1:
1579 lr = (pc - 2) | 1u; // return address
1580 Rm = Bits32(opcode, 6, 3);
1581 // if m == 15 then UNPREDICTABLE;
1582 if (Rm == 15)
1583 return false;
1584 if (InITBlock() && !LastInITBlock())
1585 return false;
1586 break;
1587 case eEncodingA1:
1588 lr = pc - 4; // return address
1589 Rm = Bits32(opcode, 3, 0);
1590 // if m == 15 then UNPREDICTABLE;
1591 if (Rm == 15)
1592 return false;
1593 break;
1594 default:
1595 return false;
1596 }
1597 addr_t target = ReadCoreReg (Rm, &success);
1598 if (!success)
1599 return false;
1600 RegisterInfo dwarf_reg;
1601 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
1602 context.SetRegister (dwarf_reg);
1603 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1604 return false;
1605 if (!BXWritePC(context, target))
1606 return false;
1607 }
1608 return true;
1609 }
1610
1611 // Branch and Exchange causes a branch to an address and instruction set specified by a register.
1612 bool
EmulateBXRm(const uint32_t opcode,const ARMEncoding encoding)1613 EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding)
1614 {
1615 #if 0
1616 // ARM pseudo code...
1617 if (ConditionPassed())
1618 {
1619 EncodingSpecificOperations();
1620 BXWritePC(R[m]);
1621 }
1622 #endif
1623
1624 if (ConditionPassed(opcode))
1625 {
1626 EmulateInstruction::Context context;
1627 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1628 uint32_t Rm; // the register with the target address
1629 switch (encoding) {
1630 case eEncodingT1:
1631 Rm = Bits32(opcode, 6, 3);
1632 if (InITBlock() && !LastInITBlock())
1633 return false;
1634 break;
1635 case eEncodingA1:
1636 Rm = Bits32(opcode, 3, 0);
1637 break;
1638 default:
1639 return false;
1640 }
1641 bool success = false;
1642 addr_t target = ReadCoreReg (Rm, &success);
1643 if (!success)
1644 return false;
1645
1646 RegisterInfo dwarf_reg;
1647 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
1648 context.SetRegister (dwarf_reg);
1649 if (!BXWritePC(context, target))
1650 return false;
1651 }
1652 return true;
1653 }
1654
1655 // Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1656 // address and instruction set specified by a register as though it were a BX instruction.
1657 //
1658 // TODO: Emulate Jazelle architecture?
1659 // We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1660 bool
EmulateBXJRm(const uint32_t opcode,const ARMEncoding encoding)1661 EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding)
1662 {
1663 #if 0
1664 // ARM pseudo code...
1665 if (ConditionPassed())
1666 {
1667 EncodingSpecificOperations();
1668 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
1669 BXWritePC(R[m]);
1670 else
1671 if JazelleAcceptsExecution() then
1672 SwitchToJazelleExecution();
1673 else
1674 SUBARCHITECTURE_DEFINED handler call;
1675 }
1676 #endif
1677
1678 if (ConditionPassed(opcode))
1679 {
1680 EmulateInstruction::Context context;
1681 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1682 uint32_t Rm; // the register with the target address
1683 switch (encoding) {
1684 case eEncodingT1:
1685 Rm = Bits32(opcode, 19, 16);
1686 if (BadReg(Rm))
1687 return false;
1688 if (InITBlock() && !LastInITBlock())
1689 return false;
1690 break;
1691 case eEncodingA1:
1692 Rm = Bits32(opcode, 3, 0);
1693 if (Rm == 15)
1694 return false;
1695 break;
1696 default:
1697 return false;
1698 }
1699 bool success = false;
1700 addr_t target = ReadCoreReg (Rm, &success);
1701 if (!success)
1702 return false;
1703
1704 RegisterInfo dwarf_reg;
1705 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
1706 context.SetRegister (dwarf_reg);
1707 if (!BXWritePC(context, target))
1708 return false;
1709 }
1710 return true;
1711 }
1712
1713 // Set r7 to point to some ip offset.
1714 // SUB (immediate)
1715 bool
EmulateSUBR7IPImm(const uint32_t opcode,const ARMEncoding encoding)1716 EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding)
1717 {
1718 #if 0
1719 // ARM pseudo code...
1720 if (ConditionPassed())
1721 {
1722 EncodingSpecificOperations();
1723 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
1724 if d == 15 then // Can only occur for ARM encoding
1725 ALUWritePC(result); // setflags is always FALSE here
1726 else
1727 R[d] = result;
1728 if setflags then
1729 APSR.N = result<31>;
1730 APSR.Z = IsZeroBit(result);
1731 APSR.C = carry;
1732 APSR.V = overflow;
1733 }
1734 #endif
1735
1736 if (ConditionPassed(opcode))
1737 {
1738 bool success = false;
1739 const addr_t ip = ReadCoreReg (12, &success);
1740 if (!success)
1741 return false;
1742 uint32_t imm32;
1743 switch (encoding) {
1744 case eEncodingA1:
1745 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1746 break;
1747 default:
1748 return false;
1749 }
1750 addr_t ip_offset = imm32;
1751 addr_t addr = ip - ip_offset; // the adjusted ip value
1752
1753 EmulateInstruction::Context context;
1754 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1755 RegisterInfo dwarf_reg;
1756 GetRegisterInfo (eRegisterKindDWARF, dwarf_r12, dwarf_reg);
1757 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
1758
1759 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
1760 return false;
1761 }
1762 return true;
1763 }
1764
1765 // Set ip to point to some stack offset.
1766 // SUB (SP minus immediate)
1767 bool
EmulateSUBIPSPImm(const uint32_t opcode,const ARMEncoding encoding)1768 EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding)
1769 {
1770 #if 0
1771 // ARM pseudo code...
1772 if (ConditionPassed())
1773 {
1774 EncodingSpecificOperations();
1775 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
1776 if d == 15 then // Can only occur for ARM encoding
1777 ALUWritePC(result); // setflags is always FALSE here
1778 else
1779 R[d] = result;
1780 if setflags then
1781 APSR.N = result<31>;
1782 APSR.Z = IsZeroBit(result);
1783 APSR.C = carry;
1784 APSR.V = overflow;
1785 }
1786 #endif
1787
1788 if (ConditionPassed(opcode))
1789 {
1790 bool success = false;
1791 const addr_t sp = ReadCoreReg (SP_REG, &success);
1792 if (!success)
1793 return false;
1794 uint32_t imm32;
1795 switch (encoding) {
1796 case eEncodingA1:
1797 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1798 break;
1799 default:
1800 return false;
1801 }
1802 addr_t sp_offset = imm32;
1803 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1804
1805 EmulateInstruction::Context context;
1806 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1807 RegisterInfo dwarf_reg;
1808 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, dwarf_reg);
1809 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
1810
1811 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
1812 return false;
1813 }
1814 return true;
1815 }
1816
1817 // This instruction subtracts an immediate value from the SP value, and writes
1818 // the result to the destination register.
1819 //
1820 // If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
1821 bool
EmulateSUBSPImm(const uint32_t opcode,const ARMEncoding encoding)1822 EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding)
1823 {
1824 #if 0
1825 // ARM pseudo code...
1826 if (ConditionPassed())
1827 {
1828 EncodingSpecificOperations();
1829 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
1830 if d == 15 then // Can only occur for ARM encoding
1831 ALUWritePC(result); // setflags is always FALSE here
1832 else
1833 R[d] = result;
1834 if setflags then
1835 APSR.N = result<31>;
1836 APSR.Z = IsZeroBit(result);
1837 APSR.C = carry;
1838 APSR.V = overflow;
1839 }
1840 #endif
1841
1842 bool success = false;
1843 if (ConditionPassed(opcode))
1844 {
1845 const addr_t sp = ReadCoreReg (SP_REG, &success);
1846 if (!success)
1847 return false;
1848
1849 uint32_t Rd;
1850 bool setflags;
1851 uint32_t imm32;
1852 switch (encoding) {
1853 case eEncodingT1:
1854 Rd = 13;
1855 setflags = false;
1856 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1857 break;
1858 case eEncodingT2:
1859 Rd = Bits32(opcode, 11, 8);
1860 setflags = BitIsSet(opcode, 20);
1861 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1862 if (Rd == 15 && setflags)
1863 return EmulateCMPImm(opcode, eEncodingT2);
1864 if (Rd == 15 && !setflags)
1865 return false;
1866 break;
1867 case eEncodingT3:
1868 Rd = Bits32(opcode, 11, 8);
1869 setflags = false;
1870 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1871 if (Rd == 15)
1872 return false;
1873 break;
1874 case eEncodingA1:
1875 Rd = Bits32(opcode, 15, 12);
1876 setflags = BitIsSet(opcode, 20);
1877 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1878
1879 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
1880 if (Rd == 15 && setflags)
1881 return EmulateSUBSPcLrEtc (opcode, encoding);
1882 break;
1883 default:
1884 return false;
1885 }
1886 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1887
1888 EmulateInstruction::Context context;
1889 if (Rd == 13)
1890 {
1891 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong
1892 // value gets passed down to context.SetImmediateSigned.
1893 context.type = EmulateInstruction::eContextAdjustStackPointer;
1894 context.SetImmediateSigned (-imm64); // the stack pointer offset
1895 }
1896 else
1897 {
1898 context.type = EmulateInstruction::eContextImmediate;
1899 context.SetNoArgs ();
1900 }
1901
1902 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
1903 return false;
1904 }
1905 return true;
1906 }
1907
1908 // A store operation to the stack that also updates the SP.
1909 bool
EmulateSTRRtSP(const uint32_t opcode,const ARMEncoding encoding)1910 EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding)
1911 {
1912 #if 0
1913 // ARM pseudo code...
1914 if (ConditionPassed())
1915 {
1916 EncodingSpecificOperations();
1917 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1918 address = if index then offset_addr else R[n];
1919 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1920 if wback then R[n] = offset_addr;
1921 }
1922 #endif
1923
1924 bool conditional = false;
1925 bool success = false;
1926 if (ConditionPassed(opcode, &conditional))
1927 {
1928 const uint32_t addr_byte_size = GetAddressByteSize();
1929 const addr_t sp = ReadCoreReg (SP_REG, &success);
1930 if (!success)
1931 return false;
1932 uint32_t Rt; // the source register
1933 uint32_t imm12;
1934 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that.
1935
1936 bool index;
1937 bool add;
1938 bool wback;
1939 switch (encoding) {
1940 case eEncodingA1:
1941 Rt = Bits32(opcode, 15, 12);
1942 imm12 = Bits32(opcode, 11, 0);
1943 Rn = Bits32 (opcode, 19, 16);
1944
1945 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
1946 return false;
1947
1948 index = BitIsSet (opcode, 24);
1949 add = BitIsSet (opcode, 23);
1950 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
1951
1952 if (wback && ((Rn == 15) || (Rn == Rt)))
1953 return false;
1954 break;
1955 default:
1956 return false;
1957 }
1958 addr_t offset_addr;
1959 if (add)
1960 offset_addr = sp + imm12;
1961 else
1962 offset_addr = sp - imm12;
1963
1964 addr_t addr;
1965 if (index)
1966 addr = offset_addr;
1967 else
1968 addr = sp;
1969
1970 EmulateInstruction::Context context;
1971 if (conditional)
1972 context.type = EmulateInstruction::eContextRegisterStore;
1973 else
1974 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1975 RegisterInfo sp_reg;
1976 RegisterInfo dwarf_reg;
1977
1978 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
1979 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rt, dwarf_reg);
1980 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
1981 if (Rt != 15)
1982 {
1983 uint32_t reg_value = ReadCoreReg(Rt, &success);
1984 if (!success)
1985 return false;
1986 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
1987 return false;
1988 }
1989 else
1990 {
1991 const uint32_t pc = ReadCoreReg(PC_REG, &success);
1992 if (!success)
1993 return false;
1994 if (!MemUWrite (context, addr, pc, addr_byte_size))
1995 return false;
1996 }
1997
1998
1999 if (wback)
2000 {
2001 context.type = EmulateInstruction::eContextAdjustStackPointer;
2002 context.SetImmediateSigned (addr - sp);
2003 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr))
2004 return false;
2005 }
2006 }
2007 return true;
2008 }
2009
2010 // Vector Push stores multiple extension registers to the stack.
2011 // It also updates SP to point to the start of the stored data.
2012 bool
EmulateVPUSH(const uint32_t opcode,const ARMEncoding encoding)2013 EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding)
2014 {
2015 #if 0
2016 // ARM pseudo code...
2017 if (ConditionPassed())
2018 {
2019 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2020 address = SP - imm32;
2021 SP = SP - imm32;
2022 if single_regs then
2023 for r = 0 to regs-1
2024 MemA[address,4] = S[d+r]; address = address+4;
2025 else
2026 for r = 0 to regs-1
2027 // Store as two word-aligned words in the correct order for current endianness.
2028 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
2029 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
2030 address = address+8;
2031 }
2032 #endif
2033
2034 bool success = false;
2035 bool conditional = false;
2036 if (ConditionPassed(opcode, &conditional))
2037 {
2038 const uint32_t addr_byte_size = GetAddressByteSize();
2039 const addr_t sp = ReadCoreReg (SP_REG, &success);
2040 if (!success)
2041 return false;
2042 bool single_regs;
2043 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2044 uint32_t imm32; // stack offset
2045 uint32_t regs; // number of registers
2046 switch (encoding) {
2047 case eEncodingT1:
2048 case eEncodingA1:
2049 single_regs = false;
2050 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
2051 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2052 // If UInt(imm8) is odd, see "FSTMX".
2053 regs = Bits32(opcode, 7, 0) / 2;
2054 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2055 if (regs == 0 || regs > 16 || (d + regs) > 32)
2056 return false;
2057 break;
2058 case eEncodingT2:
2059 case eEncodingA2:
2060 single_regs = true;
2061 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
2062 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2063 regs = Bits32(opcode, 7, 0);
2064 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2065 if (regs == 0 || regs > 16 || (d + regs) > 32)
2066 return false;
2067 break;
2068 default:
2069 return false;
2070 }
2071 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2072 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2073 addr_t sp_offset = imm32;
2074 addr_t addr = sp - sp_offset;
2075 uint32_t i;
2076
2077 EmulateInstruction::Context context;
2078 if (conditional)
2079 context.type = EmulateInstruction::eContextRegisterStore;
2080 else
2081 context.type = EmulateInstruction::eContextPushRegisterOnStack;
2082 RegisterInfo dwarf_reg;
2083 RegisterInfo sp_reg;
2084 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
2085 for (i=0; i<regs; ++i)
2086 {
2087 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
2088 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
2089 // uint64_t to accommodate 64-bit registers.
2090 uint64_t reg_value = ReadRegisterUnsigned (&dwarf_reg, 0, &success);
2091 if (!success)
2092 return false;
2093 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
2094 return false;
2095 addr += reg_byte_size;
2096 }
2097
2098 context.type = EmulateInstruction::eContextAdjustStackPointer;
2099 context.SetImmediateSigned (-sp_offset);
2100
2101 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
2102 return false;
2103 }
2104 return true;
2105 }
2106
2107 // Vector Pop loads multiple extension registers from the stack.
2108 // It also updates SP to point just above the loaded data.
2109 bool
EmulateVPOP(const uint32_t opcode,const ARMEncoding encoding)2110 EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding)
2111 {
2112 #if 0
2113 // ARM pseudo code...
2114 if (ConditionPassed())
2115 {
2116 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2117 address = SP;
2118 SP = SP + imm32;
2119 if single_regs then
2120 for r = 0 to regs-1
2121 S[d+r] = MemA[address,4]; address = address+4;
2122 else
2123 for r = 0 to regs-1
2124 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
2125 // Combine the word-aligned words in the correct order for current endianness.
2126 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
2127 }
2128 #endif
2129
2130 bool success = false;
2131 bool conditional = false;
2132 if (ConditionPassed(opcode, &conditional))
2133 {
2134 const uint32_t addr_byte_size = GetAddressByteSize();
2135 const addr_t sp = ReadCoreReg (SP_REG, &success);
2136 if (!success)
2137 return false;
2138 bool single_regs;
2139 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2140 uint32_t imm32; // stack offset
2141 uint32_t regs; // number of registers
2142 switch (encoding) {
2143 case eEncodingT1:
2144 case eEncodingA1:
2145 single_regs = false;
2146 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
2147 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2148 // If UInt(imm8) is odd, see "FLDMX".
2149 regs = Bits32(opcode, 7, 0) / 2;
2150 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2151 if (regs == 0 || regs > 16 || (d + regs) > 32)
2152 return false;
2153 break;
2154 case eEncodingT2:
2155 case eEncodingA2:
2156 single_regs = true;
2157 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
2158 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2159 regs = Bits32(opcode, 7, 0);
2160 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2161 if (regs == 0 || regs > 16 || (d + regs) > 32)
2162 return false;
2163 break;
2164 default:
2165 return false;
2166 }
2167 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2168 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2169 addr_t sp_offset = imm32;
2170 addr_t addr = sp;
2171 uint32_t i;
2172 uint64_t data; // uint64_t to accomodate 64-bit registers.
2173
2174 EmulateInstruction::Context context;
2175 if (conditional)
2176 context.type = EmulateInstruction::eContextRegisterLoad;
2177 else
2178 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2179 RegisterInfo dwarf_reg;
2180 RegisterInfo sp_reg;
2181 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
2182 for (i=0; i<regs; ++i)
2183 {
2184 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
2185 context.SetRegisterPlusOffset (sp_reg, addr - sp);
2186 data = MemARead(context, addr, reg_byte_size, 0, &success);
2187 if (!success)
2188 return false;
2189 if (!WriteRegisterUnsigned(context, &dwarf_reg, data))
2190 return false;
2191 addr += reg_byte_size;
2192 }
2193
2194 context.type = EmulateInstruction::eContextAdjustStackPointer;
2195 context.SetImmediateSigned (sp_offset);
2196
2197 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2198 return false;
2199 }
2200 return true;
2201 }
2202
2203 // SVC (previously SWI)
2204 bool
EmulateSVC(const uint32_t opcode,const ARMEncoding encoding)2205 EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding)
2206 {
2207 #if 0
2208 // ARM pseudo code...
2209 if (ConditionPassed())
2210 {
2211 EncodingSpecificOperations();
2212 CallSupervisor();
2213 }
2214 #endif
2215
2216 bool success = false;
2217
2218 if (ConditionPassed(opcode))
2219 {
2220 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2221 addr_t lr; // next instruction address
2222 if (!success)
2223 return false;
2224 uint32_t imm32; // the immediate constant
2225 uint32_t mode; // ARM or Thumb mode
2226 switch (encoding) {
2227 case eEncodingT1:
2228 lr = (pc + 2) | 1u; // return address
2229 imm32 = Bits32(opcode, 7, 0);
2230 mode = eModeThumb;
2231 break;
2232 case eEncodingA1:
2233 lr = pc + 4; // return address
2234 imm32 = Bits32(opcode, 23, 0);
2235 mode = eModeARM;
2236 break;
2237 default:
2238 return false;
2239 }
2240
2241 EmulateInstruction::Context context;
2242 context.type = EmulateInstruction::eContextSupervisorCall;
2243 context.SetISAAndImmediate (mode, imm32);
2244 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2245 return false;
2246 }
2247 return true;
2248 }
2249
2250 // If Then makes up to four following instructions (the IT block) conditional.
2251 bool
EmulateIT(const uint32_t opcode,const ARMEncoding encoding)2252 EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding)
2253 {
2254 #if 0
2255 // ARM pseudo code...
2256 EncodingSpecificOperations();
2257 ITSTATE.IT<7:0> = firstcond:mask;
2258 #endif
2259
2260 m_it_session.InitIT(Bits32(opcode, 7, 0));
2261 return true;
2262 }
2263
2264 bool
EmulateNop(const uint32_t opcode,const ARMEncoding encoding)2265 EmulateInstructionARM::EmulateNop (const uint32_t opcode, const ARMEncoding encoding)
2266 {
2267 // NOP, nothing to do...
2268 return true;
2269 }
2270
2271 // Branch causes a branch to a target address.
2272 bool
EmulateB(const uint32_t opcode,const ARMEncoding encoding)2273 EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding)
2274 {
2275 #if 0
2276 // ARM pseudo code...
2277 if (ConditionPassed())
2278 {
2279 EncodingSpecificOperations();
2280 BranchWritePC(PC + imm32);
2281 }
2282 #endif
2283
2284 bool success = false;
2285
2286 if (ConditionPassed(opcode))
2287 {
2288 EmulateInstruction::Context context;
2289 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2290 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2291 if (!success)
2292 return false;
2293 addr_t target; // target address
2294 int32_t imm32; // PC-relative offset
2295 switch (encoding) {
2296 case eEncodingT1:
2297 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2298 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
2299 target = pc + imm32;
2300 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
2301 break;
2302 case eEncodingT2:
2303 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
2304 target = pc + imm32;
2305 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
2306 break;
2307 case eEncodingT3:
2308 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2309 {
2310 uint32_t S = Bit32(opcode, 26);
2311 uint32_t imm6 = Bits32(opcode, 21, 16);
2312 uint32_t J1 = Bit32(opcode, 13);
2313 uint32_t J2 = Bit32(opcode, 11);
2314 uint32_t imm11 = Bits32(opcode, 10, 0);
2315 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
2316 imm32 = llvm::SignExtend32<21>(imm21);
2317 target = pc + imm32;
2318 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
2319 break;
2320 }
2321 case eEncodingT4:
2322 {
2323 uint32_t S = Bit32(opcode, 26);
2324 uint32_t imm10 = Bits32(opcode, 25, 16);
2325 uint32_t J1 = Bit32(opcode, 13);
2326 uint32_t J2 = Bit32(opcode, 11);
2327 uint32_t imm11 = Bits32(opcode, 10, 0);
2328 uint32_t I1 = !(J1 ^ S);
2329 uint32_t I2 = !(J2 ^ S);
2330 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
2331 imm32 = llvm::SignExtend32<25>(imm25);
2332 target = pc + imm32;
2333 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
2334 break;
2335 }
2336 case eEncodingA1:
2337 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
2338 target = pc + imm32;
2339 context.SetISAAndImmediateSigned (eModeARM, 8 + imm32);
2340 break;
2341 default:
2342 return false;
2343 }
2344 if (!BranchWritePC(context, target))
2345 return false;
2346 }
2347 return true;
2348 }
2349
2350 // Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2351 // zero and conditionally branch forward a constant value. They do not affect the condition flags.
2352 // CBNZ, CBZ
2353 bool
EmulateCB(const uint32_t opcode,const ARMEncoding encoding)2354 EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding)
2355 {
2356 #if 0
2357 // ARM pseudo code...
2358 EncodingSpecificOperations();
2359 if nonzero ^ IsZero(R[n]) then
2360 BranchWritePC(PC + imm32);
2361 #endif
2362
2363 bool success = false;
2364
2365 // Read the register value from the operand register Rn.
2366 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
2367 if (!success)
2368 return false;
2369
2370 EmulateInstruction::Context context;
2371 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2372 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2373 if (!success)
2374 return false;
2375
2376 addr_t target; // target address
2377 uint32_t imm32; // PC-relative offset to branch forward
2378 bool nonzero;
2379 switch (encoding) {
2380 case eEncodingT1:
2381 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
2382 nonzero = BitIsSet(opcode, 11);
2383 target = pc + imm32;
2384 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
2385 break;
2386 default:
2387 return false;
2388 }
2389 if (nonzero ^ (reg_val == 0))
2390 if (!BranchWritePC(context, target))
2391 return false;
2392
2393 return true;
2394 }
2395
2396 // Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2397 // A base register provides a pointer to the table, and a second register supplies an index into the table.
2398 // The branch length is twice the value of the byte returned from the table.
2399 //
2400 // Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2401 // A base register provides a pointer to the table, and a second register supplies an index into the table.
2402 // The branch length is twice the value of the halfword returned from the table.
2403 // TBB, TBH
2404 bool
EmulateTB(const uint32_t opcode,const ARMEncoding encoding)2405 EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding)
2406 {
2407 #if 0
2408 // ARM pseudo code...
2409 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2410 if is_tbh then
2411 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2412 else
2413 halfwords = UInt(MemU[R[n]+R[m], 1]);
2414 BranchWritePC(PC + 2*halfwords);
2415 #endif
2416
2417 bool success = false;
2418
2419 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2420 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2421 bool is_tbh; // true if table branch halfword
2422 switch (encoding) {
2423 case eEncodingT1:
2424 Rn = Bits32(opcode, 19, 16);
2425 Rm = Bits32(opcode, 3, 0);
2426 is_tbh = BitIsSet(opcode, 4);
2427 if (Rn == 13 || BadReg(Rm))
2428 return false;
2429 if (InITBlock() && !LastInITBlock())
2430 return false;
2431 break;
2432 default:
2433 return false;
2434 }
2435
2436 // Read the address of the table from the operand register Rn.
2437 // The PC can be used, in which case the table immediately follows this instruction.
2438 uint32_t base = ReadCoreReg(Rm, &success);
2439 if (!success)
2440 return false;
2441
2442 // the table index
2443 uint32_t index = ReadCoreReg(Rm, &success);
2444 if (!success)
2445 return false;
2446
2447 // the offsetted table address
2448 addr_t addr = base + (is_tbh ? index*2 : index);
2449
2450 // PC-relative offset to branch forward
2451 EmulateInstruction::Context context;
2452 context.type = EmulateInstruction::eContextTableBranchReadMemory;
2453 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
2454 if (!success)
2455 return false;
2456
2457 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2458 if (!success)
2459 return false;
2460
2461 // target address
2462 addr_t target = pc + offset;
2463 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2464 context.SetISAAndImmediateSigned (eModeThumb, 4 + offset);
2465
2466 if (!BranchWritePC(context, target))
2467 return false;
2468
2469 return true;
2470 }
2471
2472 // This instruction adds an immediate value to a register value, and writes the result to the destination register.
2473 // It can optionally update the condition flags based on the result.
2474 bool
EmulateADDImmThumb(const uint32_t opcode,const ARMEncoding encoding)2475 EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding)
2476 {
2477 #if 0
2478 if ConditionPassed() then
2479 EncodingSpecificOperations();
2480 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2481 R[d] = result;
2482 if setflags then
2483 APSR.N = result<31>;
2484 APSR.Z = IsZeroBit(result);
2485 APSR.C = carry;
2486 APSR.V = overflow;
2487 #endif
2488
2489 bool success = false;
2490
2491 if (ConditionPassed(opcode))
2492 {
2493 uint32_t d;
2494 uint32_t n;
2495 bool setflags;
2496 uint32_t imm32;
2497 uint32_t carry_out;
2498
2499 //EncodingSpecificOperations();
2500 switch (encoding)
2501 {
2502 case eEncodingT1:
2503 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2504 d = Bits32 (opcode, 2, 0);
2505 n = Bits32 (opcode, 5, 3);
2506 setflags = !InITBlock();
2507 imm32 = Bits32 (opcode, 8,6);
2508
2509 break;
2510
2511 case eEncodingT2:
2512 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2513 d = Bits32 (opcode, 10, 8);
2514 n = Bits32 (opcode, 10, 8);
2515 setflags = !InITBlock();
2516 imm32 = Bits32 (opcode, 7, 0);
2517
2518 break;
2519
2520 case eEncodingT3:
2521 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
2522 // if Rn == '1101' then SEE ADD (SP plus immediate);
2523 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8);
2524 d = Bits32 (opcode, 11, 8);
2525 n = Bits32 (opcode, 19, 16);
2526 setflags = BitIsSet (opcode, 20);
2527 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2528
2529 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2530 if (BadReg (d) || (n == 15))
2531 return false;
2532
2533 break;
2534
2535 case eEncodingT4:
2536 {
2537 // if Rn == '1111' then SEE ADR;
2538 // if Rn == '1101' then SEE ADD (SP plus immediate);
2539 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2540 d = Bits32 (opcode, 11, 8);
2541 n = Bits32 (opcode, 19, 16);
2542 setflags = false;
2543 uint32_t i = Bit32 (opcode, 26);
2544 uint32_t imm3 = Bits32 (opcode, 14, 12);
2545 uint32_t imm8 = Bits32 (opcode, 7, 0);
2546 imm32 = (i << 11) | (imm3 << 8) | imm8;
2547
2548 // if BadReg(d) then UNPREDICTABLE;
2549 if (BadReg (d))
2550 return false;
2551
2552 break;
2553 }
2554 default:
2555 return false;
2556 }
2557
2558 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2559 if (!success)
2560 return false;
2561
2562 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2563 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2564
2565 RegisterInfo reg_n;
2566 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
2567
2568 EmulateInstruction::Context context;
2569 context.type = eContextArithmetic;
2570 context.SetRegisterPlusOffset (reg_n, imm32);
2571
2572 //R[d] = result;
2573 //if setflags then
2574 //APSR.N = result<31>;
2575 //APSR.Z = IsZeroBit(result);
2576 //APSR.C = carry;
2577 //APSR.V = overflow;
2578 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2579 return false;
2580
2581 }
2582 return true;
2583 }
2584
2585 // This instruction adds an immediate value to a register value, and writes the result to the destination
2586 // register. It can optionally update the condition flags based on the result.
2587 bool
EmulateADDImmARM(const uint32_t opcode,const ARMEncoding encoding)2588 EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding)
2589 {
2590 #if 0
2591 // ARM pseudo code...
2592 if ConditionPassed() then
2593 EncodingSpecificOperations();
2594 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2595 if d == 15 then
2596 ALUWritePC(result); // setflags is always FALSE here
2597 else
2598 R[d] = result;
2599 if setflags then
2600 APSR.N = result<31>;
2601 APSR.Z = IsZeroBit(result);
2602 APSR.C = carry;
2603 APSR.V = overflow;
2604 #endif
2605
2606 bool success = false;
2607
2608 if (ConditionPassed(opcode))
2609 {
2610 uint32_t Rd, Rn;
2611 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2612 bool setflags;
2613 switch (encoding)
2614 {
2615 case eEncodingA1:
2616 Rd = Bits32(opcode, 15, 12);
2617 Rn = Bits32(opcode, 19, 16);
2618 setflags = BitIsSet(opcode, 20);
2619 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2620 break;
2621 default:
2622 return false;
2623 }
2624
2625 // Read the first operand.
2626 uint32_t val1 = ReadCoreReg(Rn, &success);
2627 if (!success)
2628 return false;
2629
2630 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2631
2632 EmulateInstruction::Context context;
2633 context.type = eContextArithmetic;
2634 RegisterInfo dwarf_reg;
2635 GetRegisterInfo (eRegisterKindDWARF, Rn, dwarf_reg);
2636 context.SetRegisterPlusOffset (dwarf_reg, imm32);
2637
2638 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2639 return false;
2640 }
2641 return true;
2642 }
2643
2644 // This instruction adds a register value and an optionally-shifted register value, and writes the result
2645 // to the destination register. It can optionally update the condition flags based on the result.
2646 bool
EmulateADDReg(const uint32_t opcode,const ARMEncoding encoding)2647 EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding)
2648 {
2649 #if 0
2650 // ARM pseudo code...
2651 if ConditionPassed() then
2652 EncodingSpecificOperations();
2653 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2654 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2655 if d == 15 then
2656 ALUWritePC(result); // setflags is always FALSE here
2657 else
2658 R[d] = result;
2659 if setflags then
2660 APSR.N = result<31>;
2661 APSR.Z = IsZeroBit(result);
2662 APSR.C = carry;
2663 APSR.V = overflow;
2664 #endif
2665
2666 bool success = false;
2667
2668 if (ConditionPassed(opcode))
2669 {
2670 uint32_t Rd, Rn, Rm;
2671 ARM_ShifterType shift_t;
2672 uint32_t shift_n; // the shift applied to the value read from Rm
2673 bool setflags;
2674 switch (encoding)
2675 {
2676 case eEncodingT1:
2677 Rd = Bits32(opcode, 2, 0);
2678 Rn = Bits32(opcode, 5, 3);
2679 Rm = Bits32(opcode, 8, 6);
2680 setflags = !InITBlock();
2681 shift_t = SRType_LSL;
2682 shift_n = 0;
2683 break;
2684 case eEncodingT2:
2685 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2686 Rm = Bits32(opcode, 6, 3);
2687 setflags = false;
2688 shift_t = SRType_LSL;
2689 shift_n = 0;
2690 if (Rn == 15 && Rm == 15)
2691 return false;
2692 if (Rd == 15 && InITBlock() && !LastInITBlock())
2693 return false;
2694 break;
2695 case eEncodingA1:
2696 Rd = Bits32(opcode, 15, 12);
2697 Rn = Bits32(opcode, 19, 16);
2698 Rm = Bits32(opcode, 3, 0);
2699 setflags = BitIsSet(opcode, 20);
2700 shift_n = DecodeImmShiftARM(opcode, shift_t);
2701 break;
2702 default:
2703 return false;
2704 }
2705
2706 // Read the first operand.
2707 uint32_t val1 = ReadCoreReg(Rn, &success);
2708 if (!success)
2709 return false;
2710
2711 // Read the second operand.
2712 uint32_t val2 = ReadCoreReg(Rm, &success);
2713 if (!success)
2714 return false;
2715
2716 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
2717 if (!success)
2718 return false;
2719 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
2720
2721 EmulateInstruction::Context context;
2722 context.type = eContextArithmetic;
2723 RegisterInfo op1_reg;
2724 RegisterInfo op2_reg;
2725 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, op1_reg);
2726 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, op2_reg);
2727 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
2728
2729 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2730 return false;
2731 }
2732 return true;
2733 }
2734
2735 // Compare Negative (immediate) adds a register value and an immediate value.
2736 // It updates the condition flags based on the result, and discards the result.
2737 bool
EmulateCMNImm(const uint32_t opcode,const ARMEncoding encoding)2738 EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding)
2739 {
2740 #if 0
2741 // ARM pseudo code...
2742 if ConditionPassed() then
2743 EncodingSpecificOperations();
2744 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2745 APSR.N = result<31>;
2746 APSR.Z = IsZeroBit(result);
2747 APSR.C = carry;
2748 APSR.V = overflow;
2749 #endif
2750
2751 bool success = false;
2752
2753 uint32_t Rn; // the first operand
2754 uint32_t imm32; // the immediate value to be compared with
2755 switch (encoding) {
2756 case eEncodingT1:
2757 Rn = Bits32(opcode, 19, 16);
2758 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2759 if (Rn == 15)
2760 return false;
2761 break;
2762 case eEncodingA1:
2763 Rn = Bits32(opcode, 19, 16);
2764 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2765 break;
2766 default:
2767 return false;
2768 }
2769 // Read the register value from the operand register Rn.
2770 uint32_t reg_val = ReadCoreReg(Rn, &success);
2771 if (!success)
2772 return false;
2773
2774 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
2775
2776 EmulateInstruction::Context context;
2777 context.type = EmulateInstruction::eContextImmediate;
2778 context.SetNoArgs ();
2779 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2780 return false;
2781
2782 return true;
2783 }
2784
2785 // Compare Negative (register) adds a register value and an optionally-shifted register value.
2786 // It updates the condition flags based on the result, and discards the result.
2787 bool
EmulateCMNReg(const uint32_t opcode,const ARMEncoding encoding)2788 EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding)
2789 {
2790 #if 0
2791 // ARM pseudo code...
2792 if ConditionPassed() then
2793 EncodingSpecificOperations();
2794 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2795 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2796 APSR.N = result<31>;
2797 APSR.Z = IsZeroBit(result);
2798 APSR.C = carry;
2799 APSR.V = overflow;
2800 #endif
2801
2802 bool success = false;
2803
2804 uint32_t Rn; // the first operand
2805 uint32_t Rm; // the second operand
2806 ARM_ShifterType shift_t;
2807 uint32_t shift_n; // the shift applied to the value read from Rm
2808 switch (encoding) {
2809 case eEncodingT1:
2810 Rn = Bits32(opcode, 2, 0);
2811 Rm = Bits32(opcode, 5, 3);
2812 shift_t = SRType_LSL;
2813 shift_n = 0;
2814 break;
2815 case eEncodingT2:
2816 Rn = Bits32(opcode, 19, 16);
2817 Rm = Bits32(opcode, 3, 0);
2818 shift_n = DecodeImmShiftThumb(opcode, shift_t);
2819 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2820 if (Rn == 15 || BadReg(Rm))
2821 return false;
2822 break;
2823 case eEncodingA1:
2824 Rn = Bits32(opcode, 19, 16);
2825 Rm = Bits32(opcode, 3, 0);
2826 shift_n = DecodeImmShiftARM(opcode, shift_t);
2827 break;
2828 default:
2829 return false;
2830 }
2831 // Read the register value from register Rn.
2832 uint32_t val1 = ReadCoreReg(Rn, &success);
2833 if (!success)
2834 return false;
2835
2836 // Read the register value from register Rm.
2837 uint32_t val2 = ReadCoreReg(Rm, &success);
2838 if (!success)
2839 return false;
2840
2841 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
2842 if (!success)
2843 return false;
2844 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
2845
2846 EmulateInstruction::Context context;
2847 context.type = EmulateInstruction::eContextImmediate;
2848 context.SetNoArgs();
2849 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2850 return false;
2851
2852 return true;
2853 }
2854
2855 // Compare (immediate) subtracts an immediate value from a register value.
2856 // It updates the condition flags based on the result, and discards the result.
2857 bool
EmulateCMPImm(const uint32_t opcode,const ARMEncoding encoding)2858 EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding)
2859 {
2860 #if 0
2861 // ARM pseudo code...
2862 if ConditionPassed() then
2863 EncodingSpecificOperations();
2864 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2865 APSR.N = result<31>;
2866 APSR.Z = IsZeroBit(result);
2867 APSR.C = carry;
2868 APSR.V = overflow;
2869 #endif
2870
2871 bool success = false;
2872
2873 uint32_t Rn; // the first operand
2874 uint32_t imm32; // the immediate value to be compared with
2875 switch (encoding) {
2876 case eEncodingT1:
2877 Rn = Bits32(opcode, 10, 8);
2878 imm32 = Bits32(opcode, 7, 0);
2879 break;
2880 case eEncodingT2:
2881 Rn = Bits32(opcode, 19, 16);
2882 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2883 if (Rn == 15)
2884 return false;
2885 break;
2886 case eEncodingA1:
2887 Rn = Bits32(opcode, 19, 16);
2888 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2889 break;
2890 default:
2891 return false;
2892 }
2893 // Read the register value from the operand register Rn.
2894 uint32_t reg_val = ReadCoreReg(Rn, &success);
2895 if (!success)
2896 return false;
2897
2898 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2899
2900 EmulateInstruction::Context context;
2901 context.type = EmulateInstruction::eContextImmediate;
2902 context.SetNoArgs ();
2903 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2904 return false;
2905
2906 return true;
2907 }
2908
2909 // Compare (register) subtracts an optionally-shifted register value from a register value.
2910 // It updates the condition flags based on the result, and discards the result.
2911 bool
EmulateCMPReg(const uint32_t opcode,const ARMEncoding encoding)2912 EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding)
2913 {
2914 #if 0
2915 // ARM pseudo code...
2916 if ConditionPassed() then
2917 EncodingSpecificOperations();
2918 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2919 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2920 APSR.N = result<31>;
2921 APSR.Z = IsZeroBit(result);
2922 APSR.C = carry;
2923 APSR.V = overflow;
2924 #endif
2925
2926 bool success = false;
2927
2928 uint32_t Rn; // the first operand
2929 uint32_t Rm; // the second operand
2930 ARM_ShifterType shift_t;
2931 uint32_t shift_n; // the shift applied to the value read from Rm
2932 switch (encoding) {
2933 case eEncodingT1:
2934 Rn = Bits32(opcode, 2, 0);
2935 Rm = Bits32(opcode, 5, 3);
2936 shift_t = SRType_LSL;
2937 shift_n = 0;
2938 break;
2939 case eEncodingT2:
2940 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2941 Rm = Bits32(opcode, 6, 3);
2942 shift_t = SRType_LSL;
2943 shift_n = 0;
2944 if (Rn < 8 && Rm < 8)
2945 return false;
2946 if (Rn == 15 || Rm == 15)
2947 return false;
2948 break;
2949 case eEncodingA1:
2950 Rn = Bits32(opcode, 19, 16);
2951 Rm = Bits32(opcode, 3, 0);
2952 shift_n = DecodeImmShiftARM(opcode, shift_t);
2953 break;
2954 default:
2955 return false;
2956 }
2957 // Read the register value from register Rn.
2958 uint32_t val1 = ReadCoreReg(Rn, &success);
2959 if (!success)
2960 return false;
2961
2962 // Read the register value from register Rm.
2963 uint32_t val2 = ReadCoreReg(Rm, &success);
2964 if (!success)
2965 return false;
2966
2967 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
2968 if (!success)
2969 return false;
2970 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
2971
2972 EmulateInstruction::Context context;
2973 context.type = EmulateInstruction::eContextImmediate;
2974 context.SetNoArgs();
2975 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2976 return false;
2977
2978 return true;
2979 }
2980
2981 // Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2982 // shifting in copies of its sign bit, and writes the result to the destination register. It can
2983 // optionally update the condition flags based on the result.
2984 bool
EmulateASRImm(const uint32_t opcode,const ARMEncoding encoding)2985 EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding)
2986 {
2987 #if 0
2988 // ARM pseudo code...
2989 if ConditionPassed() then
2990 EncodingSpecificOperations();
2991 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2992 if d == 15 then // Can only occur for ARM encoding
2993 ALUWritePC(result); // setflags is always FALSE here
2994 else
2995 R[d] = result;
2996 if setflags then
2997 APSR.N = result<31>;
2998 APSR.Z = IsZeroBit(result);
2999 APSR.C = carry;
3000 // APSR.V unchanged
3001 #endif
3002
3003 return EmulateShiftImm (opcode, encoding, SRType_ASR);
3004 }
3005
3006 // Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
3007 // shifting in copies of its sign bit, and writes the result to the destination register.
3008 // The variable number of bits is read from the bottom byte of a register. It can optionally update
3009 // the condition flags based on the result.
3010 bool
EmulateASRReg(const uint32_t opcode,const ARMEncoding encoding)3011 EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding)
3012 {
3013 #if 0
3014 // ARM pseudo code...
3015 if ConditionPassed() then
3016 EncodingSpecificOperations();
3017 shift_n = UInt(R[m]<7:0>);
3018 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
3019 R[d] = result;
3020 if setflags then
3021 APSR.N = result<31>;
3022 APSR.Z = IsZeroBit(result);
3023 APSR.C = carry;
3024 // APSR.V unchanged
3025 #endif
3026
3027 return EmulateShiftReg (opcode, encoding, SRType_ASR);
3028 }
3029
3030 // Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
3031 // shifting in zeros, and writes the result to the destination register. It can optionally
3032 // update the condition flags based on the result.
3033 bool
EmulateLSLImm(const uint32_t opcode,const ARMEncoding encoding)3034 EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding)
3035 {
3036 #if 0
3037 // ARM pseudo code...
3038 if ConditionPassed() then
3039 EncodingSpecificOperations();
3040 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
3041 if d == 15 then // Can only occur for ARM encoding
3042 ALUWritePC(result); // setflags is always FALSE here
3043 else
3044 R[d] = result;
3045 if setflags then
3046 APSR.N = result<31>;
3047 APSR.Z = IsZeroBit(result);
3048 APSR.C = carry;
3049 // APSR.V unchanged
3050 #endif
3051
3052 return EmulateShiftImm (opcode, encoding, SRType_LSL);
3053 }
3054
3055 // Logical Shift Left (register) shifts a register value left by a variable number of bits,
3056 // shifting in zeros, and writes the result to the destination register. The variable number
3057 // of bits is read from the bottom byte of a register. It can optionally update the condition
3058 // flags based on the result.
3059 bool
EmulateLSLReg(const uint32_t opcode,const ARMEncoding encoding)3060 EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding)
3061 {
3062 #if 0
3063 // ARM pseudo code...
3064 if ConditionPassed() then
3065 EncodingSpecificOperations();
3066 shift_n = UInt(R[m]<7:0>);
3067 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
3068 R[d] = result;
3069 if setflags then
3070 APSR.N = result<31>;
3071 APSR.Z = IsZeroBit(result);
3072 APSR.C = carry;
3073 // APSR.V unchanged
3074 #endif
3075
3076 return EmulateShiftReg (opcode, encoding, SRType_LSL);
3077 }
3078
3079 // Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
3080 // shifting in zeros, and writes the result to the destination register. It can optionally
3081 // update the condition flags based on the result.
3082 bool
EmulateLSRImm(const uint32_t opcode,const ARMEncoding encoding)3083 EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding)
3084 {
3085 #if 0
3086 // ARM pseudo code...
3087 if ConditionPassed() then
3088 EncodingSpecificOperations();
3089 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3090 if d == 15 then // Can only occur for ARM encoding
3091 ALUWritePC(result); // setflags is always FALSE here
3092 else
3093 R[d] = result;
3094 if setflags then
3095 APSR.N = result<31>;
3096 APSR.Z = IsZeroBit(result);
3097 APSR.C = carry;
3098 // APSR.V unchanged
3099 #endif
3100
3101 return EmulateShiftImm (opcode, encoding, SRType_LSR);
3102 }
3103
3104 // Logical Shift Right (register) shifts a register value right by a variable number of bits,
3105 // shifting in zeros, and writes the result to the destination register. The variable number
3106 // of bits is read from the bottom byte of a register. It can optionally update the condition
3107 // flags based on the result.
3108 bool
EmulateLSRReg(const uint32_t opcode,const ARMEncoding encoding)3109 EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding)
3110 {
3111 #if 0
3112 // ARM pseudo code...
3113 if ConditionPassed() then
3114 EncodingSpecificOperations();
3115 shift_n = UInt(R[m]<7:0>);
3116 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3117 R[d] = result;
3118 if setflags then
3119 APSR.N = result<31>;
3120 APSR.Z = IsZeroBit(result);
3121 APSR.C = carry;
3122 // APSR.V unchanged
3123 #endif
3124
3125 return EmulateShiftReg (opcode, encoding, SRType_LSR);
3126 }
3127
3128 // Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
3129 // The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3130 // It can optionally update the condition flags based on the result.
3131 bool
EmulateRORImm(const uint32_t opcode,const ARMEncoding encoding)3132 EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding)
3133 {
3134 #if 0
3135 // ARM pseudo code...
3136 if ConditionPassed() then
3137 EncodingSpecificOperations();
3138 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3139 if d == 15 then // Can only occur for ARM encoding
3140 ALUWritePC(result); // setflags is always FALSE here
3141 else
3142 R[d] = result;
3143 if setflags then
3144 APSR.N = result<31>;
3145 APSR.Z = IsZeroBit(result);
3146 APSR.C = carry;
3147 // APSR.V unchanged
3148 #endif
3149
3150 return EmulateShiftImm (opcode, encoding, SRType_ROR);
3151 }
3152
3153 // Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
3154 // The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3155 // The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
3156 // flags based on the result.
3157 bool
EmulateRORReg(const uint32_t opcode,const ARMEncoding encoding)3158 EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding)
3159 {
3160 #if 0
3161 // ARM pseudo code...
3162 if ConditionPassed() then
3163 EncodingSpecificOperations();
3164 shift_n = UInt(R[m]<7:0>);
3165 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3166 R[d] = result;
3167 if setflags then
3168 APSR.N = result<31>;
3169 APSR.Z = IsZeroBit(result);
3170 APSR.C = carry;
3171 // APSR.V unchanged
3172 #endif
3173
3174 return EmulateShiftReg (opcode, encoding, SRType_ROR);
3175 }
3176
3177 // Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
3178 // with the carry flag shifted into bit [31].
3179 //
3180 // RRX can optionally update the condition flags based on the result.
3181 // In that case, bit [0] is shifted into the carry flag.
3182 bool
EmulateRRX(const uint32_t opcode,const ARMEncoding encoding)3183 EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding)
3184 {
3185 #if 0
3186 // ARM pseudo code...
3187 if ConditionPassed() then
3188 EncodingSpecificOperations();
3189 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3190 if d == 15 then // Can only occur for ARM encoding
3191 ALUWritePC(result); // setflags is always FALSE here
3192 else
3193 R[d] = result;
3194 if setflags then
3195 APSR.N = result<31>;
3196 APSR.Z = IsZeroBit(result);
3197 APSR.C = carry;
3198 // APSR.V unchanged
3199 #endif
3200
3201 return EmulateShiftImm (opcode, encoding, SRType_RRX);
3202 }
3203
3204 bool
EmulateShiftImm(const uint32_t opcode,const ARMEncoding encoding,ARM_ShifterType shift_type)3205 EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
3206 {
3207 // assert(shift_type == SRType_ASR
3208 // || shift_type == SRType_LSL
3209 // || shift_type == SRType_LSR
3210 // || shift_type == SRType_ROR
3211 // || shift_type == SRType_RRX);
3212
3213 bool success = false;
3214
3215 if (ConditionPassed(opcode))
3216 {
3217 uint32_t Rd; // the destination register
3218 uint32_t Rm; // the first operand register
3219 uint32_t imm5; // encoding for the shift amount
3220 uint32_t carry; // the carry bit after the shift operation
3221 bool setflags;
3222
3223 // Special case handling!
3224 // A8.6.139 ROR (immediate) -- Encoding T1
3225 ARMEncoding use_encoding = encoding;
3226 if (shift_type == SRType_ROR && use_encoding == eEncodingT1)
3227 {
3228 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
3229 // have the same decoding of bit fields as the other Thumb2 shift operations.
3230 use_encoding = eEncodingT2;
3231 }
3232
3233 switch (use_encoding) {
3234 case eEncodingT1:
3235 // Due to the above special case handling!
3236 if (shift_type == SRType_ROR)
3237 return false;
3238
3239 Rd = Bits32(opcode, 2, 0);
3240 Rm = Bits32(opcode, 5, 3);
3241 setflags = !InITBlock();
3242 imm5 = Bits32(opcode, 10, 6);
3243 break;
3244 case eEncodingT2:
3245 // A8.6.141 RRX
3246 // There's no imm form of RRX instructions.
3247 if (shift_type == SRType_RRX)
3248 return false;
3249
3250 Rd = Bits32(opcode, 11, 8);
3251 Rm = Bits32(opcode, 3, 0);
3252 setflags = BitIsSet(opcode, 20);
3253 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3254 if (BadReg(Rd) || BadReg(Rm))
3255 return false;
3256 break;
3257 case eEncodingA1:
3258 Rd = Bits32(opcode, 15, 12);
3259 Rm = Bits32(opcode, 3, 0);
3260 setflags = BitIsSet(opcode, 20);
3261 imm5 = Bits32(opcode, 11, 7);
3262 break;
3263 default:
3264 return false;
3265 }
3266
3267 // A8.6.139 ROR (immediate)
3268 if (shift_type == SRType_ROR && imm5 == 0)
3269 shift_type = SRType_RRX;
3270
3271 // Get the first operand.
3272 uint32_t value = ReadCoreReg (Rm, &success);
3273 if (!success)
3274 return false;
3275
3276 // Decode the shift amount if not RRX.
3277 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
3278
3279 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3280 if (!success)
3281 return false;
3282
3283 // The context specifies that an immediate is to be moved into Rd.
3284 EmulateInstruction::Context context;
3285 context.type = EmulateInstruction::eContextImmediate;
3286 context.SetNoArgs ();
3287
3288 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3289 return false;
3290 }
3291 return true;
3292 }
3293
3294 bool
EmulateShiftReg(const uint32_t opcode,const ARMEncoding encoding,ARM_ShifterType shift_type)3295 EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
3296 {
3297 // assert(shift_type == SRType_ASR
3298 // || shift_type == SRType_LSL
3299 // || shift_type == SRType_LSR
3300 // || shift_type == SRType_ROR);
3301
3302 bool success = false;
3303
3304 if (ConditionPassed(opcode))
3305 {
3306 uint32_t Rd; // the destination register
3307 uint32_t Rn; // the first operand register
3308 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3309 uint32_t carry; // the carry bit after the shift operation
3310 bool setflags;
3311 switch (encoding) {
3312 case eEncodingT1:
3313 Rd = Bits32(opcode, 2, 0);
3314 Rn = Rd;
3315 Rm = Bits32(opcode, 5, 3);
3316 setflags = !InITBlock();
3317 break;
3318 case eEncodingT2:
3319 Rd = Bits32(opcode, 11, 8);
3320 Rn = Bits32(opcode, 19, 16);
3321 Rm = Bits32(opcode, 3, 0);
3322 setflags = BitIsSet(opcode, 20);
3323 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3324 return false;
3325 break;
3326 case eEncodingA1:
3327 Rd = Bits32(opcode, 15, 12);
3328 Rn = Bits32(opcode, 3, 0);
3329 Rm = Bits32(opcode, 11, 8);
3330 setflags = BitIsSet(opcode, 20);
3331 if (Rd == 15 || Rn == 15 || Rm == 15)
3332 return false;
3333 break;
3334 default:
3335 return false;
3336 }
3337
3338 // Get the first operand.
3339 uint32_t value = ReadCoreReg (Rn, &success);
3340 if (!success)
3341 return false;
3342 // Get the Rm register content.
3343 uint32_t val = ReadCoreReg (Rm, &success);
3344 if (!success)
3345 return false;
3346
3347 // Get the shift amount.
3348 uint32_t amt = Bits32(val, 7, 0);
3349
3350 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3351 if (!success)
3352 return false;
3353
3354 // The context specifies that an immediate is to be moved into Rd.
3355 EmulateInstruction::Context context;
3356 context.type = EmulateInstruction::eContextImmediate;
3357 context.SetNoArgs ();
3358
3359 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3360 return false;
3361 }
3362 return true;
3363 }
3364
3365 // LDM loads multiple registers from consecutive memory locations, using an
3366 // address from a base register. Optionally the address just above the highest of those locations
3367 // can be written back to the base register.
3368 bool
EmulateLDM(const uint32_t opcode,const ARMEncoding encoding)3369 EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding)
3370 {
3371 #if 0
3372 // ARM pseudo code...
3373 if ConditionPassed()
3374 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3375 address = R[n];
3376
3377 for i = 0 to 14
3378 if registers<i> == '1' then
3379 R[i] = MemA[address, 4]; address = address + 4;
3380 if registers<15> == '1' then
3381 LoadWritePC (MemA[address, 4]);
3382
3383 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3384 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3385
3386 #endif
3387
3388 bool success = false;
3389 bool conditional = false;
3390 if (ConditionPassed(opcode, &conditional))
3391 {
3392 uint32_t n;
3393 uint32_t registers = 0;
3394 bool wback;
3395 const uint32_t addr_byte_size = GetAddressByteSize();
3396 switch (encoding)
3397 {
3398 case eEncodingT1:
3399 // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0');
3400 n = Bits32 (opcode, 10, 8);
3401 registers = Bits32 (opcode, 7, 0);
3402 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
3403 wback = BitIsClear (registers, n);
3404 // if BitCount(registers) < 1 then UNPREDICTABLE;
3405 if (BitCount(registers) < 1)
3406 return false;
3407 break;
3408 case eEncodingT2:
3409 // if W == '1' && Rn == '1101' then SEE POP;
3410 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
3411 n = Bits32 (opcode, 19, 16);
3412 registers = Bits32 (opcode, 15, 0);
3413 registers = registers & 0xdfff; // Make sure bit 13 is zero.
3414 wback = BitIsSet (opcode, 21);
3415
3416 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
3417 if ((n == 15)
3418 || (BitCount (registers) < 2)
3419 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3420 return false;
3421
3422 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3423 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
3424 return false;
3425
3426 // if wback && registers<n> == '1' then UNPREDICTABLE;
3427 if (wback
3428 && BitIsSet (registers, n))
3429 return false;
3430 break;
3431
3432 case eEncodingA1:
3433 n = Bits32 (opcode, 19, 16);
3434 registers = Bits32 (opcode, 15, 0);
3435 wback = BitIsSet (opcode, 21);
3436 if ((n == 15)
3437 || (BitCount (registers) < 1))
3438 return false;
3439 break;
3440 default:
3441 return false;
3442 }
3443
3444 int32_t offset = 0;
3445 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3446 if (!success)
3447 return false;
3448
3449 EmulateInstruction::Context context;
3450 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3451 RegisterInfo dwarf_reg;
3452 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
3453 context.SetRegisterPlusOffset (dwarf_reg, offset);
3454
3455 for (int i = 0; i < 14; ++i)
3456 {
3457 if (BitIsSet (registers, i))
3458 {
3459 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3460 context.SetRegisterPlusOffset (dwarf_reg, offset);
3461 if (wback && (n == 13)) // Pop Instruction
3462 {
3463 if (conditional)
3464 context.type = EmulateInstruction::eContextRegisterLoad;
3465 else
3466 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3467 }
3468
3469 // R[i] = MemA [address, 4]; address = address + 4;
3470 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
3471 if (!success)
3472 return false;
3473
3474 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3475 return false;
3476
3477 offset += addr_byte_size;
3478 }
3479 }
3480
3481 if (BitIsSet (registers, 15))
3482 {
3483 //LoadWritePC (MemA [address, 4]);
3484 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3485 context.SetRegisterPlusOffset (dwarf_reg, offset);
3486 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
3487 if (!success)
3488 return false;
3489 // In ARMv5T and above, this is an interworking branch.
3490 if (!LoadWritePC(context, data))
3491 return false;
3492 }
3493
3494 if (wback && BitIsClear (registers, n))
3495 {
3496 // R[n] = R[n] + 4 * BitCount (registers)
3497 int32_t offset = addr_byte_size * BitCount (registers);
3498 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3499 context.SetRegisterPlusOffset (dwarf_reg, offset);
3500
3501 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3502 return false;
3503 }
3504 if (wback && BitIsSet (registers, n))
3505 // R[n] bits(32) UNKNOWN;
3506 return WriteBits32Unknown (n);
3507 }
3508 return true;
3509 }
3510
3511 // LDMDA loads multiple registers from consecutive memory locations using an address from a base register.
3512 // The consecutive memory locations end at this address and the address just below the lowest of those locations
3513 // can optionally be written back to the base register.
3514 bool
EmulateLDMDA(const uint32_t opcode,const ARMEncoding encoding)3515 EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding)
3516 {
3517 #if 0
3518 // ARM pseudo code...
3519 if ConditionPassed() then
3520 EncodingSpecificOperations();
3521 address = R[n] - 4*BitCount(registers) + 4;
3522
3523 for i = 0 to 14
3524 if registers<i> == '1' then
3525 R[i] = MemA[address,4]; address = address + 4;
3526
3527 if registers<15> == '1' then
3528 LoadWritePC(MemA[address,4]);
3529
3530 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3531 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
3532 #endif
3533
3534 bool success = false;
3535
3536 if (ConditionPassed(opcode))
3537 {
3538 uint32_t n;
3539 uint32_t registers = 0;
3540 bool wback;
3541 const uint32_t addr_byte_size = GetAddressByteSize();
3542
3543 // EncodingSpecificOperations();
3544 switch (encoding)
3545 {
3546 case eEncodingA1:
3547 // n = UInt(Rn); registers = register_list; wback = (W == '1');
3548 n = Bits32 (opcode, 19, 16);
3549 registers = Bits32 (opcode, 15, 0);
3550 wback = BitIsSet (opcode, 21);
3551
3552 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3553 if ((n == 15) || (BitCount (registers) < 1))
3554 return false;
3555
3556 break;
3557
3558 default:
3559 return false;
3560 }
3561 // address = R[n] - 4*BitCount(registers) + 4;
3562
3563 int32_t offset = 0;
3564 addr_t Rn = ReadCoreReg (n, &success);
3565
3566 if (!success)
3567 return false;
3568
3569 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size;
3570
3571 EmulateInstruction::Context context;
3572 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3573 RegisterInfo dwarf_reg;
3574 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
3575 context.SetRegisterPlusOffset (dwarf_reg, offset);
3576
3577 // for i = 0 to 14
3578 for (int i = 0; i < 14; ++i)
3579 {
3580 // if registers<i> == '1' then
3581 if (BitIsSet (registers, i))
3582 {
3583 // R[i] = MemA[address,4]; address = address + 4;
3584 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
3585 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
3586 if (!success)
3587 return false;
3588 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3589 return false;
3590 offset += addr_byte_size;
3591 }
3592 }
3593
3594 // if registers<15> == '1' then
3595 // LoadWritePC(MemA[address,4]);
3596 if (BitIsSet (registers, 15))
3597 {
3598 context.SetRegisterPlusOffset (dwarf_reg, offset);
3599 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
3600 if (!success)
3601 return false;
3602 // In ARMv5T and above, this is an interworking branch.
3603 if (!LoadWritePC(context, data))
3604 return false;
3605 }
3606
3607 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3608 if (wback && BitIsClear (registers, n))
3609 {
3610 if (!success)
3611 return false;
3612
3613 offset = (addr_byte_size * BitCount (registers)) * -1;
3614 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3615 context.SetImmediateSigned (offset);
3616 addr_t addr = Rn + offset;
3617 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3618 return false;
3619 }
3620
3621 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
3622 if (wback && BitIsSet (registers, n))
3623 return WriteBits32Unknown (n);
3624 }
3625 return true;
3626 }
3627
3628 // LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3629 // consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3630 // be optionally written back to the base register.
3631 bool
EmulateLDMDB(const uint32_t opcode,const ARMEncoding encoding)3632 EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding)
3633 {
3634 #if 0
3635 // ARM pseudo code...
3636 if ConditionPassed() then
3637 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3638 address = R[n] - 4*BitCount(registers);
3639
3640 for i = 0 to 14
3641 if registers<i> == '1' then
3642 R[i] = MemA[address,4]; address = address + 4;
3643 if registers<15> == '1' then
3644 LoadWritePC(MemA[address,4]);
3645
3646 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3647 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3648 #endif
3649
3650 bool success = false;
3651
3652 if (ConditionPassed(opcode))
3653 {
3654 uint32_t n;
3655 uint32_t registers = 0;
3656 bool wback;
3657 const uint32_t addr_byte_size = GetAddressByteSize();
3658 switch (encoding)
3659 {
3660 case eEncodingT1:
3661 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
3662 n = Bits32 (opcode, 19, 16);
3663 registers = Bits32 (opcode, 15, 0);
3664 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
3665 wback = BitIsSet (opcode, 21);
3666
3667 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
3668 if ((n == 15)
3669 || (BitCount (registers) < 2)
3670 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3671 return false;
3672
3673 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3674 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
3675 return false;
3676
3677 // if wback && registers<n> == '1' then UNPREDICTABLE;
3678 if (wback && BitIsSet (registers, n))
3679 return false;
3680
3681 break;
3682
3683 case eEncodingA1:
3684 // n = UInt(Rn); registers = register_list; wback = (W == '1');
3685 n = Bits32 (opcode, 19, 16);
3686 registers = Bits32 (opcode, 15, 0);
3687 wback = BitIsSet (opcode, 21);
3688
3689 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3690 if ((n == 15) || (BitCount (registers) < 1))
3691 return false;
3692
3693 break;
3694
3695 default:
3696 return false;
3697 }
3698
3699 // address = R[n] - 4*BitCount(registers);
3700
3701 int32_t offset = 0;
3702 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3703
3704 if (!success)
3705 return false;
3706
3707 addr_t address = Rn - (addr_byte_size * BitCount (registers));
3708 EmulateInstruction::Context context;
3709 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3710 RegisterInfo dwarf_reg;
3711 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
3712 context.SetRegisterPlusOffset (dwarf_reg, Rn - address);
3713
3714 for (int i = 0; i < 14; ++i)
3715 {
3716 if (BitIsSet (registers, i))
3717 {
3718 // R[i] = MemA[address,4]; address = address + 4;
3719 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
3720 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
3721 if (!success)
3722 return false;
3723
3724 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3725 return false;
3726
3727 offset += addr_byte_size;
3728 }
3729 }
3730
3731 // if registers<15> == '1' then
3732 // LoadWritePC(MemA[address,4]);
3733 if (BitIsSet (registers, 15))
3734 {
3735 context.SetRegisterPlusOffset (dwarf_reg, offset);
3736 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
3737 if (!success)
3738 return false;
3739 // In ARMv5T and above, this is an interworking branch.
3740 if (!LoadWritePC(context, data))
3741 return false;
3742 }
3743
3744 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3745 if (wback && BitIsClear (registers, n))
3746 {
3747 if (!success)
3748 return false;
3749
3750 offset = (addr_byte_size * BitCount (registers)) * -1;
3751 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3752 context.SetImmediateSigned (offset);
3753 addr_t addr = Rn + offset;
3754 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3755 return false;
3756 }
3757
3758 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3759 if (wback && BitIsSet (registers, n))
3760 return WriteBits32Unknown (n);
3761 }
3762 return true;
3763 }
3764
3765 // LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3766 // consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3767 // optinoally be written back to the base register.
3768 bool
EmulateLDMIB(const uint32_t opcode,const ARMEncoding encoding)3769 EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding)
3770 {
3771 #if 0
3772 if ConditionPassed() then
3773 EncodingSpecificOperations();
3774 address = R[n] + 4;
3775
3776 for i = 0 to 14
3777 if registers<i> == '1' then
3778 R[i] = MemA[address,4]; address = address + 4;
3779 if registers<15> == '1' then
3780 LoadWritePC(MemA[address,4]);
3781
3782 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
3783 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
3784 #endif
3785
3786 bool success = false;
3787
3788 if (ConditionPassed(opcode))
3789 {
3790 uint32_t n;
3791 uint32_t registers = 0;
3792 bool wback;
3793 const uint32_t addr_byte_size = GetAddressByteSize();
3794 switch (encoding)
3795 {
3796 case eEncodingA1:
3797 // n = UInt(Rn); registers = register_list; wback = (W == '1');
3798 n = Bits32 (opcode, 19, 16);
3799 registers = Bits32 (opcode, 15, 0);
3800 wback = BitIsSet (opcode, 21);
3801
3802 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3803 if ((n == 15) || (BitCount (registers) < 1))
3804 return false;
3805
3806 break;
3807 default:
3808 return false;
3809 }
3810 // address = R[n] + 4;
3811
3812 int32_t offset = 0;
3813 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3814
3815 if (!success)
3816 return false;
3817
3818 addr_t address = Rn + addr_byte_size;
3819
3820 EmulateInstruction::Context context;
3821 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3822 RegisterInfo dwarf_reg;
3823 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
3824 context.SetRegisterPlusOffset (dwarf_reg, offset);
3825
3826 for (int i = 0; i < 14; ++i)
3827 {
3828 if (BitIsSet (registers, i))
3829 {
3830 // R[i] = MemA[address,4]; address = address + 4;
3831
3832 context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size);
3833 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
3834 if (!success)
3835 return false;
3836
3837 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3838 return false;
3839
3840 offset += addr_byte_size;
3841 }
3842 }
3843
3844 // if registers<15> == '1' then
3845 // LoadWritePC(MemA[address,4]);
3846 if (BitIsSet (registers, 15))
3847 {
3848 context.SetRegisterPlusOffset (dwarf_reg, offset);
3849 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
3850 if (!success)
3851 return false;
3852 // In ARMv5T and above, this is an interworking branch.
3853 if (!LoadWritePC(context, data))
3854 return false;
3855 }
3856
3857 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
3858 if (wback && BitIsClear (registers, n))
3859 {
3860 if (!success)
3861 return false;
3862
3863 offset = addr_byte_size * BitCount (registers);
3864 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3865 context.SetImmediateSigned (offset);
3866 addr_t addr = Rn + offset;
3867 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3868 return false;
3869 }
3870
3871 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3872 if (wback && BitIsSet (registers, n))
3873 return WriteBits32Unknown (n);
3874 }
3875 return true;
3876 }
3877
3878 // Load Register (immediate) calculates an address from a base register value and
3879 // an immediate offset, loads a word from memory, and writes to a register.
3880 // LDR (immediate, Thumb)
3881 bool
EmulateLDRRtRnImm(const uint32_t opcode,const ARMEncoding encoding)3882 EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding)
3883 {
3884 #if 0
3885 // ARM pseudo code...
3886 if (ConditionPassed())
3887 {
3888 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3889 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3890 address = if index then offset_addr else R[n];
3891 data = MemU[address,4];
3892 if wback then R[n] = offset_addr;
3893 if t == 15 then
3894 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3895 elsif UnalignedSupport() || address<1:0> = '00' then
3896 R[t] = data;
3897 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3898 }
3899 #endif
3900
3901 bool success = false;
3902
3903 if (ConditionPassed(opcode))
3904 {
3905 uint32_t Rt; // the destination register
3906 uint32_t Rn; // the base register
3907 uint32_t imm32; // the immediate offset used to form the address
3908 addr_t offset_addr; // the offset address
3909 addr_t address; // the calculated address
3910 uint32_t data; // the literal data value from memory load
3911 bool add, index, wback;
3912 switch (encoding) {
3913 case eEncodingT1:
3914 Rt = Bits32(opcode, 2, 0);
3915 Rn = Bits32(opcode, 5, 3);
3916 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3917 // index = TRUE; add = TRUE; wback = FALSE
3918 add = true;
3919 index = true;
3920 wback = false;
3921
3922 break;
3923
3924 case eEncodingT2:
3925 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
3926 Rt = Bits32 (opcode, 10, 8);
3927 Rn = 13;
3928 imm32 = Bits32 (opcode, 7, 0) << 2;
3929
3930 // index = TRUE; add = TRUE; wback = FALSE;
3931 index = true;
3932 add = true;
3933 wback = false;
3934
3935 break;
3936
3937 case eEncodingT3:
3938 // if Rn == '1111' then SEE LDR (literal);
3939 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3940 Rt = Bits32 (opcode, 15, 12);
3941 Rn = Bits32 (opcode, 19, 16);
3942 imm32 = Bits32 (opcode, 11, 0);
3943
3944 // index = TRUE; add = TRUE; wback = FALSE;
3945 index = true;
3946 add = true;
3947 wback = false;
3948
3949 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3950 if ((Rt == 15) && InITBlock() && !LastInITBlock())
3951 return false;
3952
3953 break;
3954
3955 case eEncodingT4:
3956 // if Rn == '1111' then SEE LDR (literal);
3957 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
3958 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;
3959 // if P == '0' && W == '0' then UNDEFINED;
3960 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
3961 return false;
3962
3963 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3964 Rt = Bits32 (opcode, 15, 12);
3965 Rn = Bits32 (opcode, 19, 16);
3966 imm32 = Bits32 (opcode, 7, 0);
3967
3968 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
3969 index = BitIsSet (opcode, 10);
3970 add = BitIsSet (opcode, 9);
3971 wback = BitIsSet (opcode, 8);
3972
3973 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
3974 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock()))
3975 return false;
3976
3977 break;
3978
3979 default:
3980 return false;
3981 }
3982 uint32_t base = ReadCoreReg (Rn, &success);
3983 if (!success)
3984 return false;
3985 if (add)
3986 offset_addr = base + imm32;
3987 else
3988 offset_addr = base - imm32;
3989
3990 address = (index ? offset_addr : base);
3991
3992 RegisterInfo base_reg;
3993 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, base_reg);
3994 if (wback)
3995 {
3996 EmulateInstruction::Context ctx;
3997 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
3998 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
3999
4000 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
4001 return false;
4002 }
4003
4004 // Prepare to write to the Rt register.
4005 EmulateInstruction::Context context;
4006 context.type = EmulateInstruction::eContextRegisterLoad;
4007 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
4008
4009 // Read memory from the address.
4010 data = MemURead(context, address, 4, 0, &success);
4011 if (!success)
4012 return false;
4013
4014 if (Rt == 15)
4015 {
4016 if (Bits32(address, 1, 0) == 0)
4017 {
4018 if (!LoadWritePC(context, data))
4019 return false;
4020 }
4021 else
4022 return false;
4023 }
4024 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
4025 {
4026 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
4027 return false;
4028 }
4029 else
4030 WriteBits32Unknown (Rt);
4031 }
4032 return true;
4033 }
4034
4035 // STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
4036 // from a base register. The consecutive memory locations start at this address, and teh address just above the last
4037 // of those locations can optionally be written back to the base register.
4038 bool
EmulateSTM(const uint32_t opcode,const ARMEncoding encoding)4039 EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding)
4040 {
4041 #if 0
4042 if ConditionPassed() then
4043 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4044 address = R[n];
4045
4046 for i = 0 to 14
4047 if registers<i> == '1' then
4048 if i == n && wback && i != LowestSetBit(registers) then
4049 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
4050 else
4051 MemA[address,4] = R[i];
4052 address = address + 4;
4053
4054 if registers<15> == '1' then // Only possible for encoding A1
4055 MemA[address,4] = PCStoreValue();
4056 if wback then R[n] = R[n] + 4*BitCount(registers);
4057 #endif
4058
4059 bool success = false;
4060
4061 if (ConditionPassed(opcode))
4062 {
4063 uint32_t n;
4064 uint32_t registers = 0;
4065 bool wback;
4066 const uint32_t addr_byte_size = GetAddressByteSize();
4067
4068 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4069 switch (encoding)
4070 {
4071 case eEncodingT1:
4072 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
4073 n = Bits32 (opcode, 10, 8);
4074 registers = Bits32 (opcode, 7, 0);
4075 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
4076 wback = true;
4077
4078 // if BitCount(registers) < 1 then UNPREDICTABLE;
4079 if (BitCount (registers) < 1)
4080 return false;
4081
4082 break;
4083
4084 case eEncodingT2:
4085 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4086 n = Bits32 (opcode, 19, 16);
4087 registers = Bits32 (opcode, 15, 0);
4088 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4089 wback = BitIsSet (opcode, 21);
4090
4091 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4092 if ((n == 15) || (BitCount (registers) < 2))
4093 return false;
4094
4095 // if wback && registers<n> == '1' then UNPREDICTABLE;
4096 if (wback && BitIsSet (registers, n))
4097 return false;
4098
4099 break;
4100
4101 case eEncodingA1:
4102 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4103 n = Bits32 (opcode, 19, 16);
4104 registers = Bits32 (opcode, 15, 0);
4105 wback = BitIsSet (opcode, 21);
4106
4107 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4108 if ((n == 15) || (BitCount (registers) < 1))
4109 return false;
4110
4111 break;
4112
4113 default:
4114 return false;
4115 }
4116
4117 // address = R[n];
4118 int32_t offset = 0;
4119 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4120 if (!success)
4121 return false;
4122
4123 EmulateInstruction::Context context;
4124 context.type = EmulateInstruction::eContextRegisterStore;
4125 RegisterInfo base_reg;
4126 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4127
4128 // for i = 0 to 14
4129 uint32_t lowest_set_bit = 14;
4130 for (uint32_t i = 0; i < 14; ++i)
4131 {
4132 // if registers<i> == '1' then
4133 if (BitIsSet (registers, i))
4134 {
4135 if (i < lowest_set_bit)
4136 lowest_set_bit = i;
4137 // if i == n && wback && i != LowestSetBit(registers) then
4138 if ((i == n) && wback && (i != lowest_set_bit))
4139 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
4140 WriteBits32UnknownToMemory (address + offset);
4141 else
4142 {
4143 // MemA[address,4] = R[i];
4144 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4145 if (!success)
4146 return false;
4147
4148 RegisterInfo data_reg;
4149 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
4150 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
4151 if (!MemAWrite (context, address + offset, data, addr_byte_size))
4152 return false;
4153 }
4154
4155 // address = address + 4;
4156 offset += addr_byte_size;
4157 }
4158 }
4159
4160 // if registers<15> == '1' then // Only possible for encoding A1
4161 // MemA[address,4] = PCStoreValue();
4162 if (BitIsSet (registers, 15))
4163 {
4164 RegisterInfo pc_reg;
4165 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
4166 context.SetRegisterPlusOffset (pc_reg, 8);
4167 const uint32_t pc = ReadCoreReg (PC_REG, &success);
4168 if (!success)
4169 return false;
4170
4171 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
4172 return false;
4173 }
4174
4175 // if wback then R[n] = R[n] + 4*BitCount(registers);
4176 if (wback)
4177 {
4178 offset = addr_byte_size * BitCount (registers);
4179 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4180 context.SetImmediateSigned (offset);
4181 addr_t data = address + offset;
4182 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4183 return false;
4184 }
4185 }
4186 return true;
4187 }
4188
4189 // STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
4190 // from a base register. The consecutive memory locations end at this address, and the address just below the lowest
4191 // of those locations can optionally be written back to the base register.
4192 bool
EmulateSTMDA(const uint32_t opcode,const ARMEncoding encoding)4193 EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding)
4194 {
4195 #if 0
4196 if ConditionPassed() then
4197 EncodingSpecificOperations();
4198 address = R[n] - 4*BitCount(registers) + 4;
4199
4200 for i = 0 to 14
4201 if registers<i> == '1' then
4202 if i == n && wback && i != LowestSetBit(registers) then
4203 MemA[address,4] = bits(32) UNKNOWN;
4204 else
4205 MemA[address,4] = R[i];
4206 address = address + 4;
4207
4208 if registers<15> == '1' then
4209 MemA[address,4] = PCStoreValue();
4210
4211 if wback then R[n] = R[n] - 4*BitCount(registers);
4212 #endif
4213
4214 bool success = false;
4215
4216 if (ConditionPassed(opcode))
4217 {
4218 uint32_t n;
4219 uint32_t registers = 0;
4220 bool wback;
4221 const uint32_t addr_byte_size = GetAddressByteSize();
4222
4223 // EncodingSpecificOperations();
4224 switch (encoding)
4225 {
4226 case eEncodingA1:
4227 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4228 n = Bits32 (opcode, 19, 16);
4229 registers = Bits32 (opcode, 15, 0);
4230 wback = BitIsSet (opcode, 21);
4231
4232 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4233 if ((n == 15) || (BitCount (registers) < 1))
4234 return false;
4235 break;
4236 default:
4237 return false;
4238 }
4239
4240 // address = R[n] - 4*BitCount(registers) + 4;
4241 int32_t offset = 0;
4242 addr_t Rn = ReadCoreReg (n, &success);
4243 if (!success)
4244 return false;
4245
4246 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4;
4247
4248 EmulateInstruction::Context context;
4249 context.type = EmulateInstruction::eContextRegisterStore;
4250 RegisterInfo base_reg;
4251 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4252
4253 // for i = 0 to 14
4254 uint32_t lowest_bit_set = 14;
4255 for (uint32_t i = 0; i < 14; ++i)
4256 {
4257 // if registers<i> == '1' then
4258 if (BitIsSet (registers, i))
4259 {
4260 if (i < lowest_bit_set)
4261 lowest_bit_set = i;
4262 //if i == n && wback && i != LowestSetBit(registers) then
4263 if ((i == n) && wback && (i != lowest_bit_set))
4264 // MemA[address,4] = bits(32) UNKNOWN;
4265 WriteBits32UnknownToMemory (address + offset);
4266 else
4267 {
4268 // MemA[address,4] = R[i];
4269 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4270 if (!success)
4271 return false;
4272
4273 RegisterInfo data_reg;
4274 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
4275 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
4276 if (!MemAWrite (context, address + offset, data, addr_byte_size))
4277 return false;
4278 }
4279
4280 // address = address + 4;
4281 offset += addr_byte_size;
4282 }
4283 }
4284
4285 // if registers<15> == '1' then
4286 // MemA[address,4] = PCStoreValue();
4287 if (BitIsSet (registers, 15))
4288 {
4289 RegisterInfo pc_reg;
4290 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
4291 context.SetRegisterPlusOffset (pc_reg, 8);
4292 const uint32_t pc = ReadCoreReg (PC_REG, &success);
4293 if (!success)
4294 return false;
4295
4296 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
4297 return false;
4298 }
4299
4300 // if wback then R[n] = R[n] - 4*BitCount(registers);
4301 if (wback)
4302 {
4303 offset = (addr_byte_size * BitCount (registers)) * -1;
4304 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4305 context.SetImmediateSigned (offset);
4306 addr_t data = Rn + offset;
4307 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4308 return false;
4309 }
4310 }
4311 return true;
4312 }
4313
4314 // STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4315 // from a base register. The consecutive memory locations end just below this address, and the address of the first of
4316 // those locations can optionally be written back to the base register.
4317 bool
EmulateSTMDB(const uint32_t opcode,const ARMEncoding encoding)4318 EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding)
4319 {
4320 #if 0
4321 if ConditionPassed() then
4322 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4323 address = R[n] - 4*BitCount(registers);
4324
4325 for i = 0 to 14
4326 if registers<i> == '1' then
4327 if i == n && wback && i != LowestSetBit(registers) then
4328 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4329 else
4330 MemA[address,4] = R[i];
4331 address = address + 4;
4332
4333 if registers<15> == '1' then // Only possible for encoding A1
4334 MemA[address,4] = PCStoreValue();
4335
4336 if wback then R[n] = R[n] - 4*BitCount(registers);
4337 #endif
4338
4339
4340 bool success = false;
4341
4342 if (ConditionPassed(opcode))
4343 {
4344 uint32_t n;
4345 uint32_t registers = 0;
4346 bool wback;
4347 const uint32_t addr_byte_size = GetAddressByteSize();
4348
4349 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4350 switch (encoding)
4351 {
4352 case eEncodingT1:
4353 // if W == '1' && Rn == '1101' then SEE PUSH;
4354 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4355 {
4356 // See PUSH
4357 }
4358 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4359 n = Bits32 (opcode, 19, 16);
4360 registers = Bits32 (opcode, 15, 0);
4361 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4362 wback = BitIsSet (opcode, 21);
4363 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4364 if ((n == 15) || BitCount (registers) < 2)
4365 return false;
4366 // if wback && registers<n> == '1' then UNPREDICTABLE;
4367 if (wback && BitIsSet (registers, n))
4368 return false;
4369 break;
4370
4371 case eEncodingA1:
4372 // if W == '1' && Rn == '1101� && BitCount(register_list) >= 2 then SEE PUSH;
4373 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4374 {
4375 // See Push
4376 }
4377 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4378 n = Bits32 (opcode, 19, 16);
4379 registers = Bits32 (opcode, 15, 0);
4380 wback = BitIsSet (opcode, 21);
4381 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4382 if ((n == 15) || BitCount (registers) < 1)
4383 return false;
4384 break;
4385
4386 default:
4387 return false;
4388 }
4389
4390 // address = R[n] - 4*BitCount(registers);
4391
4392 int32_t offset = 0;
4393 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4394 if (!success)
4395 return false;
4396
4397 addr_t address = Rn - (addr_byte_size * BitCount (registers));
4398
4399 EmulateInstruction::Context context;
4400 context.type = EmulateInstruction::eContextRegisterStore;
4401 RegisterInfo base_reg;
4402 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4403
4404 // for i = 0 to 14
4405 uint32_t lowest_set_bit = 14;
4406 for (uint32_t i = 0; i < 14; ++i)
4407 {
4408 // if registers<i> == '1' then
4409 if (BitIsSet (registers, i))
4410 {
4411 if (i < lowest_set_bit)
4412 lowest_set_bit = i;
4413 // if i == n && wback && i != LowestSetBit(registers) then
4414 if ((i == n) && wback && (i != lowest_set_bit))
4415 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4416 WriteBits32UnknownToMemory (address + offset);
4417 else
4418 {
4419 // MemA[address,4] = R[i];
4420 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4421 if (!success)
4422 return false;
4423
4424 RegisterInfo data_reg;
4425 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
4426 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
4427 if (!MemAWrite (context, address + offset, data, addr_byte_size))
4428 return false;
4429 }
4430
4431 // address = address + 4;
4432 offset += addr_byte_size;
4433 }
4434 }
4435
4436 // if registers<15> == '1' then // Only possible for encoding A1
4437 // MemA[address,4] = PCStoreValue();
4438 if (BitIsSet (registers, 15))
4439 {
4440 RegisterInfo pc_reg;
4441 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
4442 context.SetRegisterPlusOffset (pc_reg, 8);
4443 const uint32_t pc = ReadCoreReg (PC_REG, &success);
4444 if (!success)
4445 return false;
4446
4447 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
4448 return false;
4449 }
4450
4451 // if wback then R[n] = R[n] - 4*BitCount(registers);
4452 if (wback)
4453 {
4454 offset = (addr_byte_size * BitCount (registers)) * -1;
4455 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4456 context.SetImmediateSigned (offset);
4457 addr_t data = Rn + offset;
4458 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4459 return false;
4460 }
4461 }
4462 return true;
4463 }
4464
4465 // STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4466 // from a base register. The consecutive memory locations start just above this address, and the address of the last
4467 // of those locations can optionally be written back to the base register.
4468 bool
EmulateSTMIB(const uint32_t opcode,const ARMEncoding encoding)4469 EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding)
4470 {
4471 #if 0
4472 if ConditionPassed() then
4473 EncodingSpecificOperations();
4474 address = R[n] + 4;
4475
4476 for i = 0 to 14
4477 if registers<i> == '1' then
4478 if i == n && wback && i != LowestSetBit(registers) then
4479 MemA[address,4] = bits(32) UNKNOWN;
4480 else
4481 MemA[address,4] = R[i];
4482 address = address + 4;
4483
4484 if registers<15> == '1' then
4485 MemA[address,4] = PCStoreValue();
4486
4487 if wback then R[n] = R[n] + 4*BitCount(registers);
4488 #endif
4489
4490 bool success = false;
4491
4492 if (ConditionPassed(opcode))
4493 {
4494 uint32_t n;
4495 uint32_t registers = 0;
4496 bool wback;
4497 const uint32_t addr_byte_size = GetAddressByteSize();
4498
4499 // EncodingSpecificOperations();
4500 switch (encoding)
4501 {
4502 case eEncodingA1:
4503 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4504 n = Bits32 (opcode, 19, 16);
4505 registers = Bits32 (opcode, 15, 0);
4506 wback = BitIsSet (opcode, 21);
4507
4508 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4509 if ((n == 15) && (BitCount (registers) < 1))
4510 return false;
4511 break;
4512 default:
4513 return false;
4514 }
4515 // address = R[n] + 4;
4516
4517 int32_t offset = 0;
4518 addr_t Rn = ReadCoreReg (n, &success);
4519 if (!success)
4520 return false;
4521
4522 addr_t address = Rn + addr_byte_size;
4523
4524 EmulateInstruction::Context context;
4525 context.type = EmulateInstruction::eContextRegisterStore;
4526 RegisterInfo base_reg;
4527 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4528
4529 uint32_t lowest_set_bit = 14;
4530 // for i = 0 to 14
4531 for (uint32_t i = 0; i < 14; ++i)
4532 {
4533 // if registers<i> == '1' then
4534 if (BitIsSet (registers, i))
4535 {
4536 if (i < lowest_set_bit)
4537 lowest_set_bit = i;
4538 // if i == n && wback && i != LowestSetBit(registers) then
4539 if ((i == n) && wback && (i != lowest_set_bit))
4540 // MemA[address,4] = bits(32) UNKNOWN;
4541 WriteBits32UnknownToMemory (address + offset);
4542 // else
4543 else
4544 {
4545 // MemA[address,4] = R[i];
4546 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4547 if (!success)
4548 return false;
4549
4550 RegisterInfo data_reg;
4551 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
4552 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size);
4553 if (!MemAWrite (context, address + offset, data, addr_byte_size))
4554 return false;
4555 }
4556
4557 // address = address + 4;
4558 offset += addr_byte_size;
4559 }
4560 }
4561
4562 // if registers<15> == '1' then
4563 // MemA[address,4] = PCStoreValue();
4564 if (BitIsSet (registers, 15))
4565 {
4566 RegisterInfo pc_reg;
4567 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
4568 context.SetRegisterPlusOffset (pc_reg, 8);
4569 const uint32_t pc = ReadCoreReg (PC_REG, &success);
4570 if (!success)
4571 return false;
4572
4573 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
4574 return false;
4575 }
4576
4577 // if wback then R[n] = R[n] + 4*BitCount(registers);
4578 if (wback)
4579 {
4580 offset = addr_byte_size * BitCount (registers);
4581 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4582 context.SetImmediateSigned (offset);
4583 addr_t data = Rn + offset;
4584 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4585 return false;
4586 }
4587 }
4588 return true;
4589 }
4590
4591 // STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4592 // from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4593 bool
EmulateSTRThumb(const uint32_t opcode,const ARMEncoding encoding)4594 EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding)
4595 {
4596 #if 0
4597 if ConditionPassed() then
4598 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4599 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4600 address = if index then offset_addr else R[n];
4601 if UnalignedSupport() || address<1:0> == '00' then
4602 MemU[address,4] = R[t];
4603 else // Can only occur before ARMv7
4604 MemU[address,4] = bits(32) UNKNOWN;
4605 if wback then R[n] = offset_addr;
4606 #endif
4607
4608 bool success = false;
4609
4610 if (ConditionPassed(opcode))
4611 {
4612 const uint32_t addr_byte_size = GetAddressByteSize();
4613
4614 uint32_t t;
4615 uint32_t n;
4616 uint32_t imm32;
4617 bool index;
4618 bool add;
4619 bool wback;
4620 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4621 switch (encoding)
4622 {
4623 case eEncodingT1:
4624 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
4625 t = Bits32 (opcode, 2, 0);
4626 n = Bits32 (opcode, 5, 3);
4627 imm32 = Bits32 (opcode, 10, 6) << 2;
4628
4629 // index = TRUE; add = TRUE; wback = FALSE;
4630 index = true;
4631 add = false;
4632 wback = false;
4633 break;
4634
4635 case eEncodingT2:
4636 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
4637 t = Bits32 (opcode, 10, 8);
4638 n = 13;
4639 imm32 = Bits32 (opcode, 7, 0) << 2;
4640
4641 // index = TRUE; add = TRUE; wback = FALSE;
4642 index = true;
4643 add = true;
4644 wback = false;
4645 break;
4646
4647 case eEncodingT3:
4648 // if Rn == '1111' then UNDEFINED;
4649 if (Bits32 (opcode, 19, 16) == 15)
4650 return false;
4651
4652 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4653 t = Bits32 (opcode, 15, 12);
4654 n = Bits32 (opcode, 19, 16);
4655 imm32 = Bits32 (opcode, 11, 0);
4656
4657 // index = TRUE; add = TRUE; wback = FALSE;
4658 index = true;
4659 add = true;
4660 wback = false;
4661
4662 // if t == 15 then UNPREDICTABLE;
4663 if (t == 15)
4664 return false;
4665 break;
4666
4667 case eEncodingT4:
4668 // if P == '1' && U == '1' && W == '0' then SEE STRT;
4669 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH;
4670 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
4671 if ((Bits32 (opcode, 19, 16) == 15)
4672 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4673 return false;
4674
4675 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4676 t = Bits32 (opcode, 15, 12);
4677 n = Bits32 (opcode, 19, 16);
4678 imm32 = Bits32 (opcode, 7, 0);
4679
4680 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
4681 index = BitIsSet (opcode, 10);
4682 add = BitIsSet (opcode, 9);
4683 wback = BitIsSet (opcode, 8);
4684
4685 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4686 if ((t == 15) || (wback && (n == t)))
4687 return false;
4688 break;
4689
4690 default:
4691 return false;
4692 }
4693
4694 addr_t offset_addr;
4695 addr_t address;
4696
4697 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4698 uint32_t base_address = ReadCoreReg (n, &success);
4699 if (!success)
4700 return false;
4701
4702 if (add)
4703 offset_addr = base_address + imm32;
4704 else
4705 offset_addr = base_address - imm32;
4706
4707 // address = if index then offset_addr else R[n];
4708 if (index)
4709 address = offset_addr;
4710 else
4711 address = base_address;
4712
4713 EmulateInstruction::Context context;
4714 context.type = eContextRegisterStore;
4715 RegisterInfo base_reg;
4716 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4717
4718 // if UnalignedSupport() || address<1:0> == '00' then
4719 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4720 {
4721 // MemU[address,4] = R[t];
4722 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4723 if (!success)
4724 return false;
4725
4726 RegisterInfo data_reg;
4727 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
4728 int32_t offset = address - base_address;
4729 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
4730 if (!MemUWrite (context, address, data, addr_byte_size))
4731 return false;
4732 }
4733 else
4734 {
4735 // MemU[address,4] = bits(32) UNKNOWN;
4736 WriteBits32UnknownToMemory (address);
4737 }
4738
4739 // if wback then R[n] = offset_addr;
4740 if (wback)
4741 {
4742 context.type = eContextRegisterLoad;
4743 context.SetAddress (offset_addr);
4744 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4745 return false;
4746 }
4747 }
4748 return true;
4749 }
4750
4751 // STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4752 // word from a register to memory. The offset register value can optionally be shifted.
4753 bool
EmulateSTRRegister(const uint32_t opcode,const ARMEncoding encoding)4754 EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding)
4755 {
4756 #if 0
4757 if ConditionPassed() then
4758 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4759 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4760 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4761 address = if index then offset_addr else R[n];
4762 if t == 15 then // Only possible for encoding A1
4763 data = PCStoreValue();
4764 else
4765 data = R[t];
4766 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
4767 MemU[address,4] = data;
4768 else // Can only occur before ARMv7
4769 MemU[address,4] = bits(32) UNKNOWN;
4770 if wback then R[n] = offset_addr;
4771 #endif
4772
4773 bool success = false;
4774
4775 if (ConditionPassed(opcode))
4776 {
4777 const uint32_t addr_byte_size = GetAddressByteSize();
4778
4779 uint32_t t;
4780 uint32_t n;
4781 uint32_t m;
4782 ARM_ShifterType shift_t;
4783 uint32_t shift_n;
4784 bool index;
4785 bool add;
4786 bool wback;
4787
4788 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4789 switch (encoding)
4790 {
4791 case eEncodingT1:
4792 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4793 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4794 t = Bits32 (opcode, 2, 0);
4795 n = Bits32 (opcode, 5, 3);
4796 m = Bits32 (opcode, 8, 6);
4797
4798 // index = TRUE; add = TRUE; wback = FALSE;
4799 index = true;
4800 add = true;
4801 wback = false;
4802
4803 // (shift_t, shift_n) = (SRType_LSL, 0);
4804 shift_t = SRType_LSL;
4805 shift_n = 0;
4806 break;
4807
4808 case eEncodingT2:
4809 // if Rn == '1111' then UNDEFINED;
4810 if (Bits32 (opcode, 19, 16) == 15)
4811 return false;
4812
4813 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4814 t = Bits32 (opcode, 15, 12);
4815 n = Bits32 (opcode, 19, 16);
4816 m = Bits32 (opcode, 3, 0);
4817
4818 // index = TRUE; add = TRUE; wback = FALSE;
4819 index = true;
4820 add = true;
4821 wback = false;
4822
4823 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4824 shift_t = SRType_LSL;
4825 shift_n = Bits32 (opcode, 5, 4);
4826
4827 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4828 if ((t == 15) || (BadReg (m)))
4829 return false;
4830 break;
4831
4832 case eEncodingA1:
4833 {
4834 // if P == '0' && W == '1' then SEE STRT;
4835 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4836 t = Bits32 (opcode, 15, 12);
4837 n = Bits32 (opcode, 19, 16);
4838 m = Bits32 (opcode, 3, 0);
4839
4840 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
4841 index = BitIsSet (opcode, 24);
4842 add = BitIsSet (opcode, 23);
4843 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4844
4845 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4846 uint32_t typ = Bits32 (opcode, 6, 5);
4847 uint32_t imm5 = Bits32 (opcode, 11, 7);
4848 shift_n = DecodeImmShift(typ, imm5, shift_t);
4849
4850 // if m == 15 then UNPREDICTABLE;
4851 if (m == 15)
4852 return false;
4853
4854 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4855 if (wback && ((n == 15) || (n == t)))
4856 return false;
4857
4858 break;
4859 }
4860 default:
4861 return false;
4862 }
4863
4864 addr_t offset_addr;
4865 addr_t address;
4866 int32_t offset = 0;
4867
4868 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4869 if (!success)
4870 return false;
4871
4872 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4873 if (!success)
4874 return false;
4875
4876 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
4877 offset = Shift (Rm_data, shift_t, shift_n, APSR_C, &success);
4878 if (!success)
4879 return false;
4880
4881 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4882 if (add)
4883 offset_addr = base_address + offset;
4884 else
4885 offset_addr = base_address - offset;
4886
4887 // address = if index then offset_addr else R[n];
4888 if (index)
4889 address = offset_addr;
4890 else
4891 address = base_address;
4892
4893 uint32_t data;
4894 // if t == 15 then // Only possible for encoding A1
4895 if (t == 15)
4896 // data = PCStoreValue();
4897 data = ReadCoreReg (PC_REG, &success);
4898 else
4899 // data = R[t];
4900 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4901
4902 if (!success)
4903 return false;
4904
4905 EmulateInstruction::Context context;
4906 context.type = eContextRegisterStore;
4907
4908 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
4909 if (UnalignedSupport ()
4910 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4911 || CurrentInstrSet() == eModeARM)
4912 {
4913 // MemU[address,4] = data;
4914
4915 RegisterInfo base_reg;
4916 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4917
4918 RegisterInfo data_reg;
4919 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
4920
4921 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4922 if (!MemUWrite (context, address, data, addr_byte_size))
4923 return false;
4924
4925 }
4926 else
4927 // MemU[address,4] = bits(32) UNKNOWN;
4928 WriteBits32UnknownToMemory (address);
4929
4930 // if wback then R[n] = offset_addr;
4931 if (wback)
4932 {
4933 context.type = eContextRegisterLoad;
4934 context.SetAddress (offset_addr);
4935 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4936 return false;
4937 }
4938
4939 }
4940 return true;
4941 }
4942
4943 bool
EmulateSTRBThumb(const uint32_t opcode,const ARMEncoding encoding)4944 EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding)
4945 {
4946 #if 0
4947 if ConditionPassed() then
4948 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4949 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4950 address = if index then offset_addr else R[n];
4951 MemU[address,1] = R[t]<7:0>;
4952 if wback then R[n] = offset_addr;
4953 #endif
4954
4955
4956 bool success = false;
4957
4958 if (ConditionPassed(opcode))
4959 {
4960 uint32_t t;
4961 uint32_t n;
4962 uint32_t imm32;
4963 bool index;
4964 bool add;
4965 bool wback;
4966 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4967 switch (encoding)
4968 {
4969 case eEncodingT1:
4970 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4971 t = Bits32 (opcode, 2, 0);
4972 n = Bits32 (opcode, 5, 3);
4973 imm32 = Bits32 (opcode, 10, 6);
4974
4975 // index = TRUE; add = TRUE; wback = FALSE;
4976 index = true;
4977 add = true;
4978 wback = false;
4979 break;
4980
4981 case eEncodingT2:
4982 // if Rn == '1111' then UNDEFINED;
4983 if (Bits32 (opcode, 19, 16) == 15)
4984 return false;
4985
4986 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4987 t = Bits32 (opcode, 15, 12);
4988 n = Bits32 (opcode, 19, 16);
4989 imm32 = Bits32 (opcode, 11, 0);
4990
4991 // index = TRUE; add = TRUE; wback = FALSE;
4992 index = true;
4993 add = true;
4994 wback = false;
4995
4996 // if BadReg(t) then UNPREDICTABLE;
4997 if (BadReg (t))
4998 return false;
4999 break;
5000
5001 case eEncodingT3:
5002 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
5003 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
5004 if (Bits32 (opcode, 19, 16) == 15)
5005 return false;
5006
5007 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5008 t = Bits32 (opcode, 15, 12);
5009 n = Bits32 (opcode, 19, 16);
5010 imm32 = Bits32 (opcode, 7, 0);
5011
5012 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
5013 index = BitIsSet (opcode, 10);
5014 add = BitIsSet (opcode, 9);
5015 wback = BitIsSet (opcode, 8);
5016
5017 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
5018 if ((BadReg (t)) || (wback && (n == t)))
5019 return false;
5020 break;
5021
5022 default:
5023 return false;
5024 }
5025
5026 addr_t offset_addr;
5027 addr_t address;
5028 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5029 if (!success)
5030 return false;
5031
5032 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5033 if (add)
5034 offset_addr = base_address + imm32;
5035 else
5036 offset_addr = base_address - imm32;
5037
5038 // address = if index then offset_addr else R[n];
5039 if (index)
5040 address = offset_addr;
5041 else
5042 address = base_address;
5043
5044 // MemU[address,1] = R[t]<7:0>
5045 RegisterInfo base_reg;
5046 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5047
5048 RegisterInfo data_reg;
5049 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
5050
5051 EmulateInstruction::Context context;
5052 context.type = eContextRegisterStore;
5053 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
5054
5055 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
5056 if (!success)
5057 return false;
5058
5059 data = Bits32 (data, 7, 0);
5060
5061 if (!MemUWrite (context, address, data, 1))
5062 return false;
5063
5064 // if wback then R[n] = offset_addr;
5065 if (wback)
5066 {
5067 context.type = eContextRegisterLoad;
5068 context.SetAddress (offset_addr);
5069 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5070 return false;
5071 }
5072
5073 }
5074
5075 return true;
5076 }
5077
5078 // STRH (register) calculates an address from a base register value and an offset register value, and stores a
5079 // halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
5080 bool
EmulateSTRHRegister(const uint32_t opcode,const ARMEncoding encoding)5081 EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding)
5082 {
5083 #if 0
5084 if ConditionPassed() then
5085 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5086 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5087 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5088 address = if index then offset_addr else R[n];
5089 if UnalignedSupport() || address<0> == '0' then
5090 MemU[address,2] = R[t]<15:0>;
5091 else // Can only occur before ARMv7
5092 MemU[address,2] = bits(16) UNKNOWN;
5093 if wback then R[n] = offset_addr;
5094 #endif
5095
5096 bool success = false;
5097
5098 if (ConditionPassed(opcode))
5099 {
5100 uint32_t t;
5101 uint32_t n;
5102 uint32_t m;
5103 bool index;
5104 bool add;
5105 bool wback;
5106 ARM_ShifterType shift_t;
5107 uint32_t shift_n;
5108
5109 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5110 switch (encoding)
5111 {
5112 case eEncodingT1:
5113 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5114 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5115 t = Bits32 (opcode, 2, 0);
5116 n = Bits32 (opcode, 5, 3);
5117 m = Bits32 (opcode, 8, 6);
5118
5119 // index = TRUE; add = TRUE; wback = FALSE;
5120 index = true;
5121 add = true;
5122 wback = false;
5123
5124 // (shift_t, shift_n) = (SRType_LSL, 0);
5125 shift_t = SRType_LSL;
5126 shift_n = 0;
5127
5128 break;
5129
5130 case eEncodingT2:
5131 // if Rn == '1111' then UNDEFINED;
5132 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5133 t = Bits32 (opcode, 15, 12);
5134 n = Bits32 (opcode, 19, 16);
5135 m = Bits32 (opcode, 3, 0);
5136 if (n == 15)
5137 return false;
5138
5139 // index = TRUE; add = TRUE; wback = FALSE;
5140 index = true;
5141 add = true;
5142 wback = false;
5143
5144 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5145 shift_t = SRType_LSL;
5146 shift_n = Bits32 (opcode, 5, 4);
5147
5148 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
5149 if (BadReg (t) || BadReg (m))
5150 return false;
5151
5152 break;
5153
5154 case eEncodingA1:
5155 // if P == '0' && W == '1' then SEE STRHT;
5156 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5157 t = Bits32 (opcode, 15, 12);
5158 n = Bits32 (opcode, 19, 16);
5159 m = Bits32 (opcode, 3, 0);
5160
5161 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
5162 index = BitIsSet (opcode, 24);
5163 add = BitIsSet (opcode, 23);
5164 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5165
5166 // (shift_t, shift_n) = (SRType_LSL, 0);
5167 shift_t = SRType_LSL;
5168 shift_n = 0;
5169
5170 // if t == 15 || m == 15 then UNPREDICTABLE;
5171 if ((t == 15) || (m == 15))
5172 return false;
5173
5174 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5175 if (wback && ((n == 15) || (n == t)))
5176 return false;
5177
5178 break;
5179
5180 default:
5181 return false;
5182 }
5183
5184 uint32_t Rm = ReadCoreReg (m, &success);
5185 if (!success)
5186 return false;
5187
5188 uint32_t Rn = ReadCoreReg (n, &success);
5189 if (!success)
5190 return false;
5191
5192 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5193 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
5194 if (!success)
5195 return false;
5196
5197 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5198 addr_t offset_addr;
5199 if (add)
5200 offset_addr = Rn + offset;
5201 else
5202 offset_addr = Rn - offset;
5203
5204 // address = if index then offset_addr else R[n];
5205 addr_t address;
5206 if (index)
5207 address = offset_addr;
5208 else
5209 address = Rn;
5210
5211 EmulateInstruction::Context context;
5212 context.type = eContextRegisterStore;
5213 RegisterInfo base_reg;
5214 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5215 RegisterInfo offset_reg;
5216 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
5217
5218 // if UnalignedSupport() || address<0> == '0' then
5219 if (UnalignedSupport() || BitIsClear (address, 0))
5220 {
5221 // MemU[address,2] = R[t]<15:0>;
5222 uint32_t Rt = ReadCoreReg (t, &success);
5223 if (!success)
5224 return false;
5225
5226 EmulateInstruction::Context context;
5227 context.type = eContextRegisterStore;
5228 RegisterInfo base_reg;
5229 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5230 RegisterInfo offset_reg;
5231 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
5232 RegisterInfo data_reg;
5233 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
5234 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
5235
5236 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
5237 return false;
5238 }
5239 else // Can only occur before ARMv7
5240 {
5241 // MemU[address,2] = bits(16) UNKNOWN;
5242 }
5243
5244 // if wback then R[n] = offset_addr;
5245 if (wback)
5246 {
5247 context.type = eContextAdjustBaseRegister;
5248 context.SetAddress (offset_addr);
5249 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5250 return false;
5251 }
5252 }
5253
5254 return true;
5255 }
5256
5257 // Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
5258 // and writes the result to the destination register. It can optionally update the condition flags
5259 // based on the result.
5260 bool
EmulateADCImm(const uint32_t opcode,const ARMEncoding encoding)5261 EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding)
5262 {
5263 #if 0
5264 // ARM pseudo code...
5265 if ConditionPassed() then
5266 EncodingSpecificOperations();
5267 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5268 if d == 15 then // Can only occur for ARM encoding
5269 ALUWritePC(result); // setflags is always FALSE here
5270 else
5271 R[d] = result;
5272 if setflags then
5273 APSR.N = result<31>;
5274 APSR.Z = IsZeroBit(result);
5275 APSR.C = carry;
5276 APSR.V = overflow;
5277 #endif
5278
5279 bool success = false;
5280
5281 if (ConditionPassed(opcode))
5282 {
5283 uint32_t Rd, Rn;
5284 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5285 bool setflags;
5286 switch (encoding)
5287 {
5288 case eEncodingT1:
5289 Rd = Bits32(opcode, 11, 8);
5290 Rn = Bits32(opcode, 19, 16);
5291 setflags = BitIsSet(opcode, 20);
5292 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5293 if (BadReg(Rd) || BadReg(Rn))
5294 return false;
5295 break;
5296 case eEncodingA1:
5297 Rd = Bits32(opcode, 15, 12);
5298 Rn = Bits32(opcode, 19, 16);
5299 setflags = BitIsSet(opcode, 20);
5300 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5301
5302 if (Rd == 15 && setflags)
5303 return EmulateSUBSPcLrEtc (opcode, encoding);
5304 break;
5305 default:
5306 return false;
5307 }
5308
5309 // Read the first operand.
5310 int32_t val1 = ReadCoreReg(Rn, &success);
5311 if (!success)
5312 return false;
5313
5314 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5315
5316 EmulateInstruction::Context context;
5317 context.type = EmulateInstruction::eContextImmediate;
5318 context.SetNoArgs ();
5319
5320 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5321 return false;
5322 }
5323 return true;
5324 }
5325
5326 // Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
5327 // register value, and writes the result to the destination register. It can optionally update the
5328 // condition flags based on the result.
5329 bool
EmulateADCReg(const uint32_t opcode,const ARMEncoding encoding)5330 EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding)
5331 {
5332 #if 0
5333 // ARM pseudo code...
5334 if ConditionPassed() then
5335 EncodingSpecificOperations();
5336 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5337 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5338 if d == 15 then // Can only occur for ARM encoding
5339 ALUWritePC(result); // setflags is always FALSE here
5340 else
5341 R[d] = result;
5342 if setflags then
5343 APSR.N = result<31>;
5344 APSR.Z = IsZeroBit(result);
5345 APSR.C = carry;
5346 APSR.V = overflow;
5347 #endif
5348
5349 bool success = false;
5350
5351 if (ConditionPassed(opcode))
5352 {
5353 uint32_t Rd, Rn, Rm;
5354 ARM_ShifterType shift_t;
5355 uint32_t shift_n; // the shift applied to the value read from Rm
5356 bool setflags;
5357 switch (encoding)
5358 {
5359 case eEncodingT1:
5360 Rd = Rn = Bits32(opcode, 2, 0);
5361 Rm = Bits32(opcode, 5, 3);
5362 setflags = !InITBlock();
5363 shift_t = SRType_LSL;
5364 shift_n = 0;
5365 break;
5366 case eEncodingT2:
5367 Rd = Bits32(opcode, 11, 8);
5368 Rn = Bits32(opcode, 19, 16);
5369 Rm = Bits32(opcode, 3, 0);
5370 setflags = BitIsSet(opcode, 20);
5371 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5372 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5373 return false;
5374 break;
5375 case eEncodingA1:
5376 Rd = Bits32(opcode, 15, 12);
5377 Rn = Bits32(opcode, 19, 16);
5378 Rm = Bits32(opcode, 3, 0);
5379 setflags = BitIsSet(opcode, 20);
5380 shift_n = DecodeImmShiftARM(opcode, shift_t);
5381
5382 if (Rd == 15 && setflags)
5383 return EmulateSUBSPcLrEtc (opcode, encoding);
5384 break;
5385 default:
5386 return false;
5387 }
5388
5389 // Read the first operand.
5390 int32_t val1 = ReadCoreReg(Rn, &success);
5391 if (!success)
5392 return false;
5393
5394 // Read the second operand.
5395 int32_t val2 = ReadCoreReg(Rm, &success);
5396 if (!success)
5397 return false;
5398
5399 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
5400 if (!success)
5401 return false;
5402 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5403
5404 EmulateInstruction::Context context;
5405 context.type = EmulateInstruction::eContextImmediate;
5406 context.SetNoArgs ();
5407
5408 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5409 return false;
5410 }
5411 return true;
5412 }
5413
5414 // This instruction adds an immediate value to the PC value to form a PC-relative address,
5415 // and writes the result to the destination register.
5416 bool
EmulateADR(const uint32_t opcode,const ARMEncoding encoding)5417 EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding)
5418 {
5419 #if 0
5420 // ARM pseudo code...
5421 if ConditionPassed() then
5422 EncodingSpecificOperations();
5423 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5424 if d == 15 then // Can only occur for ARM encodings
5425 ALUWritePC(result);
5426 else
5427 R[d] = result;
5428 #endif
5429
5430 bool success = false;
5431
5432 if (ConditionPassed(opcode))
5433 {
5434 uint32_t Rd;
5435 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5436 bool add;
5437 switch (encoding)
5438 {
5439 case eEncodingT1:
5440 Rd = Bits32(opcode, 10, 8);
5441 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5442 add = true;
5443 break;
5444 case eEncodingT2:
5445 case eEncodingT3:
5446 Rd = Bits32(opcode, 11, 8);
5447 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5448 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5449 if (BadReg(Rd))
5450 return false;
5451 break;
5452 case eEncodingA1:
5453 case eEncodingA2:
5454 Rd = Bits32(opcode, 15, 12);
5455 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5456 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5457 break;
5458 default:
5459 return false;
5460 }
5461
5462 // Read the PC value.
5463 uint32_t pc = ReadCoreReg(PC_REG, &success);
5464 if (!success)
5465 return false;
5466
5467 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5468
5469 EmulateInstruction::Context context;
5470 context.type = EmulateInstruction::eContextImmediate;
5471 context.SetNoArgs ();
5472
5473 if (!WriteCoreReg(context, result, Rd))
5474 return false;
5475 }
5476 return true;
5477 }
5478
5479 // This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5480 // to the destination register. It can optionally update the condition flags based on the result.
5481 bool
EmulateANDImm(const uint32_t opcode,const ARMEncoding encoding)5482 EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding)
5483 {
5484 #if 0
5485 // ARM pseudo code...
5486 if ConditionPassed() then
5487 EncodingSpecificOperations();
5488 result = R[n] AND imm32;
5489 if d == 15 then // Can only occur for ARM encoding
5490 ALUWritePC(result); // setflags is always FALSE here
5491 else
5492 R[d] = result;
5493 if setflags then
5494 APSR.N = result<31>;
5495 APSR.Z = IsZeroBit(result);
5496 APSR.C = carry;
5497 // APSR.V unchanged
5498 #endif
5499
5500 bool success = false;
5501
5502 if (ConditionPassed(opcode))
5503 {
5504 uint32_t Rd, Rn;
5505 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5506 bool setflags;
5507 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5508 switch (encoding)
5509 {
5510 case eEncodingT1:
5511 Rd = Bits32(opcode, 11, 8);
5512 Rn = Bits32(opcode, 19, 16);
5513 setflags = BitIsSet(opcode, 20);
5514 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5515 // if Rd == '1111' && S == '1' then SEE TST (immediate);
5516 if (Rd == 15 && setflags)
5517 return EmulateTSTImm(opcode, eEncodingT1);
5518 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5519 return false;
5520 break;
5521 case eEncodingA1:
5522 Rd = Bits32(opcode, 15, 12);
5523 Rn = Bits32(opcode, 19, 16);
5524 setflags = BitIsSet(opcode, 20);
5525 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5526
5527 if (Rd == 15 && setflags)
5528 return EmulateSUBSPcLrEtc (opcode, encoding);
5529 break;
5530 default:
5531 return false;
5532 }
5533
5534 // Read the first operand.
5535 uint32_t val1 = ReadCoreReg(Rn, &success);
5536 if (!success)
5537 return false;
5538
5539 uint32_t result = val1 & imm32;
5540
5541 EmulateInstruction::Context context;
5542 context.type = EmulateInstruction::eContextImmediate;
5543 context.SetNoArgs ();
5544
5545 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5546 return false;
5547 }
5548 return true;
5549 }
5550
5551 // This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5552 // and writes the result to the destination register. It can optionally update the condition flags
5553 // based on the result.
5554 bool
EmulateANDReg(const uint32_t opcode,const ARMEncoding encoding)5555 EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding)
5556 {
5557 #if 0
5558 // ARM pseudo code...
5559 if ConditionPassed() then
5560 EncodingSpecificOperations();
5561 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5562 result = R[n] AND shifted;
5563 if d == 15 then // Can only occur for ARM encoding
5564 ALUWritePC(result); // setflags is always FALSE here
5565 else
5566 R[d] = result;
5567 if setflags then
5568 APSR.N = result<31>;
5569 APSR.Z = IsZeroBit(result);
5570 APSR.C = carry;
5571 // APSR.V unchanged
5572 #endif
5573
5574 bool success = false;
5575
5576 if (ConditionPassed(opcode))
5577 {
5578 uint32_t Rd, Rn, Rm;
5579 ARM_ShifterType shift_t;
5580 uint32_t shift_n; // the shift applied to the value read from Rm
5581 bool setflags;
5582 uint32_t carry;
5583 switch (encoding)
5584 {
5585 case eEncodingT1:
5586 Rd = Rn = Bits32(opcode, 2, 0);
5587 Rm = Bits32(opcode, 5, 3);
5588 setflags = !InITBlock();
5589 shift_t = SRType_LSL;
5590 shift_n = 0;
5591 break;
5592 case eEncodingT2:
5593 Rd = Bits32(opcode, 11, 8);
5594 Rn = Bits32(opcode, 19, 16);
5595 Rm = Bits32(opcode, 3, 0);
5596 setflags = BitIsSet(opcode, 20);
5597 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5598 // if Rd == '1111' && S == '1' then SEE TST (register);
5599 if (Rd == 15 && setflags)
5600 return EmulateTSTReg(opcode, eEncodingT2);
5601 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5602 return false;
5603 break;
5604 case eEncodingA1:
5605 Rd = Bits32(opcode, 15, 12);
5606 Rn = Bits32(opcode, 19, 16);
5607 Rm = Bits32(opcode, 3, 0);
5608 setflags = BitIsSet(opcode, 20);
5609 shift_n = DecodeImmShiftARM(opcode, shift_t);
5610
5611 if (Rd == 15 && setflags)
5612 return EmulateSUBSPcLrEtc (opcode, encoding);
5613 break;
5614 default:
5615 return false;
5616 }
5617
5618 // Read the first operand.
5619 uint32_t val1 = ReadCoreReg(Rn, &success);
5620 if (!success)
5621 return false;
5622
5623 // Read the second operand.
5624 uint32_t val2 = ReadCoreReg(Rm, &success);
5625 if (!success)
5626 return false;
5627
5628 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
5629 if (!success)
5630 return false;
5631 uint32_t result = val1 & shifted;
5632
5633 EmulateInstruction::Context context;
5634 context.type = EmulateInstruction::eContextImmediate;
5635 context.SetNoArgs ();
5636
5637 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5638 return false;
5639 }
5640 return true;
5641 }
5642
5643 // Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5644 // immediate value, and writes the result to the destination register. It can optionally update the
5645 // condition flags based on the result.
5646 bool
EmulateBICImm(const uint32_t opcode,const ARMEncoding encoding)5647 EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding)
5648 {
5649 #if 0
5650 // ARM pseudo code...
5651 if ConditionPassed() then
5652 EncodingSpecificOperations();
5653 result = R[n] AND NOT(imm32);
5654 if d == 15 then // Can only occur for ARM encoding
5655 ALUWritePC(result); // setflags is always FALSE here
5656 else
5657 R[d] = result;
5658 if setflags then
5659 APSR.N = result<31>;
5660 APSR.Z = IsZeroBit(result);
5661 APSR.C = carry;
5662 // APSR.V unchanged
5663 #endif
5664
5665 bool success = false;
5666
5667 if (ConditionPassed(opcode))
5668 {
5669 uint32_t Rd, Rn;
5670 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5671 bool setflags;
5672 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5673 switch (encoding)
5674 {
5675 case eEncodingT1:
5676 Rd = Bits32(opcode, 11, 8);
5677 Rn = Bits32(opcode, 19, 16);
5678 setflags = BitIsSet(opcode, 20);
5679 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5680 if (BadReg(Rd) || BadReg(Rn))
5681 return false;
5682 break;
5683 case eEncodingA1:
5684 Rd = Bits32(opcode, 15, 12);
5685 Rn = Bits32(opcode, 19, 16);
5686 setflags = BitIsSet(opcode, 20);
5687 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5688
5689 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
5690 if (Rd == 15 && setflags)
5691 return EmulateSUBSPcLrEtc (opcode, encoding);
5692 break;
5693 default:
5694 return false;
5695 }
5696
5697 // Read the first operand.
5698 uint32_t val1 = ReadCoreReg(Rn, &success);
5699 if (!success)
5700 return false;
5701
5702 uint32_t result = val1 & ~imm32;
5703
5704 EmulateInstruction::Context context;
5705 context.type = EmulateInstruction::eContextImmediate;
5706 context.SetNoArgs ();
5707
5708 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5709 return false;
5710 }
5711 return true;
5712 }
5713
5714 // Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5715 // optionally-shifted register value, and writes the result to the destination register.
5716 // It can optionally update the condition flags based on the result.
5717 bool
EmulateBICReg(const uint32_t opcode,const ARMEncoding encoding)5718 EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding)
5719 {
5720 #if 0
5721 // ARM pseudo code...
5722 if ConditionPassed() then
5723 EncodingSpecificOperations();
5724 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5725 result = R[n] AND NOT(shifted);
5726 if d == 15 then // Can only occur for ARM encoding
5727 ALUWritePC(result); // setflags is always FALSE here
5728 else
5729 R[d] = result;
5730 if setflags then
5731 APSR.N = result<31>;
5732 APSR.Z = IsZeroBit(result);
5733 APSR.C = carry;
5734 // APSR.V unchanged
5735 #endif
5736
5737 bool success = false;
5738
5739 if (ConditionPassed(opcode))
5740 {
5741 uint32_t Rd, Rn, Rm;
5742 ARM_ShifterType shift_t;
5743 uint32_t shift_n; // the shift applied to the value read from Rm
5744 bool setflags;
5745 uint32_t carry;
5746 switch (encoding)
5747 {
5748 case eEncodingT1:
5749 Rd = Rn = Bits32(opcode, 2, 0);
5750 Rm = Bits32(opcode, 5, 3);
5751 setflags = !InITBlock();
5752 shift_t = SRType_LSL;
5753 shift_n = 0;
5754 break;
5755 case eEncodingT2:
5756 Rd = Bits32(opcode, 11, 8);
5757 Rn = Bits32(opcode, 19, 16);
5758 Rm = Bits32(opcode, 3, 0);
5759 setflags = BitIsSet(opcode, 20);
5760 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5761 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5762 return false;
5763 break;
5764 case eEncodingA1:
5765 Rd = Bits32(opcode, 15, 12);
5766 Rn = Bits32(opcode, 19, 16);
5767 Rm = Bits32(opcode, 3, 0);
5768 setflags = BitIsSet(opcode, 20);
5769 shift_n = DecodeImmShiftARM(opcode, shift_t);
5770
5771 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
5772 if (Rd == 15 && setflags)
5773 return EmulateSUBSPcLrEtc (opcode, encoding);
5774 break;
5775 default:
5776 return false;
5777 }
5778
5779 // Read the first operand.
5780 uint32_t val1 = ReadCoreReg(Rn, &success);
5781 if (!success)
5782 return false;
5783
5784 // Read the second operand.
5785 uint32_t val2 = ReadCoreReg(Rm, &success);
5786 if (!success)
5787 return false;
5788
5789 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
5790 if (!success)
5791 return false;
5792 uint32_t result = val1 & ~shifted;
5793
5794 EmulateInstruction::Context context;
5795 context.type = EmulateInstruction::eContextImmediate;
5796 context.SetNoArgs ();
5797
5798 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5799 return false;
5800 }
5801 return true;
5802 }
5803
5804 // LDR (immediate, ARM) calculates an address from a base register value and an immediate offset, loads a word
5805 // from memory, and writes it to a register. It can use offset, post-indexed, or pre-indexed addressing.
5806 bool
EmulateLDRImmediateARM(const uint32_t opcode,const ARMEncoding encoding)5807 EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding)
5808 {
5809 #if 0
5810 if ConditionPassed() then
5811 EncodingSpecificOperations();
5812 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5813 address = if index then offset_addr else R[n];
5814 data = MemU[address,4];
5815 if wback then R[n] = offset_addr;
5816 if t == 15 then
5817 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5818 elsif UnalignedSupport() || address<1:0> = '00' then
5819 R[t] = data;
5820 else // Can only apply before ARMv7
5821 R[t] = ROR(data, 8*UInt(address<1:0>));
5822 #endif
5823
5824 bool success = false;
5825
5826 if (ConditionPassed(opcode))
5827 {
5828 const uint32_t addr_byte_size = GetAddressByteSize();
5829
5830 uint32_t t;
5831 uint32_t n;
5832 uint32_t imm32;
5833 bool index;
5834 bool add;
5835 bool wback;
5836
5837 switch (encoding)
5838 {
5839 case eEncodingA1:
5840 // if Rn == '1111' then SEE LDR (literal);
5841 // if P == '0' && W == '1' then SEE LDRT;
5842 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP;
5843 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5844 t = Bits32 (opcode, 15, 12);
5845 n = Bits32 (opcode, 19, 16);
5846 imm32 = Bits32 (opcode, 11, 0);
5847
5848 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
5849 index = BitIsSet (opcode, 24);
5850 add = BitIsSet (opcode, 23);
5851 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5852
5853 // if wback && n == t then UNPREDICTABLE;
5854 if (wback && (n == t))
5855 return false;
5856
5857 break;
5858
5859 default:
5860 return false;
5861 }
5862
5863 addr_t address;
5864 addr_t offset_addr;
5865 addr_t base_address = ReadCoreReg (n, &success);
5866 if (!success)
5867 return false;
5868
5869 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5870 if (add)
5871 offset_addr = base_address + imm32;
5872 else
5873 offset_addr = base_address - imm32;
5874
5875 // address = if index then offset_addr else R[n];
5876 if (index)
5877 address = offset_addr;
5878 else
5879 address = base_address;
5880
5881 // data = MemU[address,4];
5882
5883 RegisterInfo base_reg;
5884 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5885
5886 EmulateInstruction::Context context;
5887 context.type = eContextRegisterLoad;
5888 context.SetRegisterPlusOffset (base_reg, address - base_address);
5889
5890 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5891 if (!success)
5892 return false;
5893
5894 // if wback then R[n] = offset_addr;
5895 if (wback)
5896 {
5897 context.type = eContextAdjustBaseRegister;
5898 context.SetAddress (offset_addr);
5899 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5900 return false;
5901 }
5902
5903 // if t == 15 then
5904 if (t == 15)
5905 {
5906 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5907 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5908 {
5909 // LoadWritePC (data);
5910 context.type = eContextRegisterLoad;
5911 context.SetRegisterPlusOffset (base_reg, address - base_address);
5912 LoadWritePC (context, data);
5913 }
5914 else
5915 return false;
5916 }
5917 // elsif UnalignedSupport() || address<1:0> = '00' then
5918 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5919 {
5920 // R[t] = data;
5921 context.type = eContextRegisterLoad;
5922 context.SetRegisterPlusOffset (base_reg, address - base_address);
5923 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5924 return false;
5925 }
5926 // else // Can only apply before ARMv7
5927 else
5928 {
5929 // R[t] = ROR(data, 8*UInt(address<1:0>));
5930 data = ROR (data, Bits32 (address, 1, 0), &success);
5931 if (!success)
5932 return false;
5933 context.type = eContextRegisterLoad;
5934 context.SetImmediate (data);
5935 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5936 return false;
5937 }
5938
5939 }
5940 return true;
5941 }
5942
5943 // LDR (register) calculates an address from a base register value and an offset register value, loads a word
5944 // from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5945 bool
EmulateLDRRegister(const uint32_t opcode,const ARMEncoding encoding)5946 EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding)
5947 {
5948 #if 0
5949 if ConditionPassed() then
5950 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5951 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5952 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5953 address = if index then offset_addr else R[n];
5954 data = MemU[address,4];
5955 if wback then R[n] = offset_addr;
5956 if t == 15 then
5957 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5958 elsif UnalignedSupport() || address<1:0> = '00' then
5959 R[t] = data;
5960 else // Can only apply before ARMv7
5961 if CurrentInstrSet() == InstrSet_ARM then
5962 R[t] = ROR(data, 8*UInt(address<1:0>));
5963 else
5964 R[t] = bits(32) UNKNOWN;
5965 #endif
5966
5967 bool success = false;
5968
5969 if (ConditionPassed(opcode))
5970 {
5971 const uint32_t addr_byte_size = GetAddressByteSize();
5972
5973 uint32_t t;
5974 uint32_t n;
5975 uint32_t m;
5976 bool index;
5977 bool add;
5978 bool wback;
5979 ARM_ShifterType shift_t;
5980 uint32_t shift_n;
5981
5982 switch (encoding)
5983 {
5984 case eEncodingT1:
5985 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5986 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5987 t = Bits32 (opcode, 2, 0);
5988 n = Bits32 (opcode, 5, 3);
5989 m = Bits32 (opcode, 8, 6);
5990
5991 // index = TRUE; add = TRUE; wback = FALSE;
5992 index = true;
5993 add = true;
5994 wback = false;
5995
5996 // (shift_t, shift_n) = (SRType_LSL, 0);
5997 shift_t = SRType_LSL;
5998 shift_n = 0;
5999
6000 break;
6001
6002 case eEncodingT2:
6003 // if Rn == '1111' then SEE LDR (literal);
6004 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6005 t = Bits32 (opcode, 15, 12);
6006 n = Bits32 (opcode, 19, 16);
6007 m = Bits32 (opcode, 3, 0);
6008
6009 // index = TRUE; add = TRUE; wback = FALSE;
6010 index = true;
6011 add = true;
6012 wback = false;
6013
6014 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6015 shift_t = SRType_LSL;
6016 shift_n = Bits32 (opcode, 5, 4);
6017
6018 // if BadReg(m) then UNPREDICTABLE;
6019 if (BadReg (m))
6020 return false;
6021
6022 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
6023 if ((t == 15) && InITBlock() && !LastInITBlock())
6024 return false;
6025
6026 break;
6027
6028 case eEncodingA1:
6029 {
6030 // if P == '0' && W == '1' then SEE LDRT;
6031 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6032 t = Bits32 (opcode, 15, 12);
6033 n = Bits32 (opcode, 19, 16);
6034 m = Bits32 (opcode, 3, 0);
6035
6036 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
6037 index = BitIsSet (opcode, 24);
6038 add = BitIsSet (opcode, 23);
6039 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6040
6041 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6042 uint32_t type = Bits32 (opcode, 6, 5);
6043 uint32_t imm5 = Bits32 (opcode, 11, 7);
6044 shift_n = DecodeImmShift (type, imm5, shift_t);
6045
6046 // if m == 15 then UNPREDICTABLE;
6047 if (m == 15)
6048 return false;
6049
6050 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6051 if (wback && ((n == 15) || (n == t)))
6052 return false;
6053 }
6054 break;
6055
6056
6057 default:
6058 return false;
6059 }
6060
6061 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6062 if (!success)
6063 return false;
6064
6065 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6066 if (!success)
6067 return false;
6068
6069 addr_t offset_addr;
6070 addr_t address;
6071
6072 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR".
6073 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C), &success);
6074 if (!success)
6075 return false;
6076
6077 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6078 if (add)
6079 offset_addr = Rn + offset;
6080 else
6081 offset_addr = Rn - offset;
6082
6083 // address = if index then offset_addr else R[n];
6084 if (index)
6085 address = offset_addr;
6086 else
6087 address = Rn;
6088
6089 // data = MemU[address,4];
6090 RegisterInfo base_reg;
6091 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6092
6093 EmulateInstruction::Context context;
6094 context.type = eContextRegisterLoad;
6095 context.SetRegisterPlusOffset (base_reg, address - Rn);
6096
6097 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
6098 if (!success)
6099 return false;
6100
6101 // if wback then R[n] = offset_addr;
6102 if (wback)
6103 {
6104 context.type = eContextAdjustBaseRegister;
6105 context.SetAddress (offset_addr);
6106 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6107 return false;
6108 }
6109
6110 // if t == 15 then
6111 if (t == 15)
6112 {
6113 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6114 if (BitIsClear (address, 1) && BitIsClear (address, 0))
6115 {
6116 context.type = eContextRegisterLoad;
6117 context.SetRegisterPlusOffset (base_reg, address - Rn);
6118 LoadWritePC (context, data);
6119 }
6120 else
6121 return false;
6122 }
6123 // elsif UnalignedSupport() || address<1:0> = '00' then
6124 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
6125 {
6126 // R[t] = data;
6127 context.type = eContextRegisterLoad;
6128 context.SetRegisterPlusOffset (base_reg, address - Rn);
6129 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6130 return false;
6131 }
6132 else // Can only apply before ARMv7
6133 {
6134 // if CurrentInstrSet() == InstrSet_ARM then
6135 if (CurrentInstrSet () == eModeARM)
6136 {
6137 // R[t] = ROR(data, 8*UInt(address<1:0>));
6138 data = ROR (data, Bits32 (address, 1, 0), &success);
6139 if (!success)
6140 return false;
6141 context.type = eContextRegisterLoad;
6142 context.SetImmediate (data);
6143 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6144 return false;
6145 }
6146 else
6147 {
6148 // R[t] = bits(32) UNKNOWN;
6149 WriteBits32Unknown (t);
6150 }
6151 }
6152 }
6153 return true;
6154 }
6155
6156 // LDRB (immediate, Thumb)
6157 bool
EmulateLDRBImmediate(const uint32_t opcode,const ARMEncoding encoding)6158 EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding)
6159 {
6160 #if 0
6161 if ConditionPassed() then
6162 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6163 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6164 address = if index then offset_addr else R[n];
6165 R[t] = ZeroExtend(MemU[address,1], 32);
6166 if wback then R[n] = offset_addr;
6167 #endif
6168
6169 bool success = false;
6170
6171 if (ConditionPassed(opcode))
6172 {
6173 uint32_t t;
6174 uint32_t n;
6175 uint32_t imm32;
6176 bool index;
6177 bool add;
6178 bool wback;
6179
6180 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6181 switch (encoding)
6182 {
6183 case eEncodingT1:
6184 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6185 t = Bits32 (opcode, 2, 0);
6186 n = Bits32 (opcode, 5, 3);
6187 imm32 = Bits32 (opcode, 10, 6);
6188
6189 // index = TRUE; add = TRUE; wback = FALSE;
6190 index = true;
6191 add = true;
6192 wback= false;
6193
6194 break;
6195
6196 case eEncodingT2:
6197 // if Rt == '1111' then SEE PLD;
6198 // if Rn == '1111' then SEE LDRB (literal);
6199 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6200 t = Bits32 (opcode, 15, 12);
6201 n = Bits32 (opcode, 19, 16);
6202 imm32 = Bits32 (opcode, 11, 0);
6203
6204 // index = TRUE; add = TRUE; wback = FALSE;
6205 index = true;
6206 add = true;
6207 wback = false;
6208
6209 // if t == 13 then UNPREDICTABLE;
6210 if (t == 13)
6211 return false;
6212
6213 break;
6214
6215 case eEncodingT3:
6216 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
6217 // if Rn == '1111' then SEE LDRB (literal);
6218 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
6219 // if P == '0' && W == '0' then UNDEFINED;
6220 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6221 return false;
6222
6223 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6224 t = Bits32 (opcode, 15, 12);
6225 n = Bits32 (opcode, 19, 16);
6226 imm32 = Bits32 (opcode, 7, 0);
6227
6228 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
6229 index = BitIsSet (opcode, 10);
6230 add = BitIsSet (opcode, 9);
6231 wback = BitIsSet (opcode, 8);
6232
6233 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6234 if (BadReg (t) || (wback && (n == t)))
6235 return false;
6236
6237 break;
6238
6239 default:
6240 return false;
6241 }
6242
6243 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6244 if (!success)
6245 return false;
6246
6247 addr_t address;
6248 addr_t offset_addr;
6249
6250 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6251 if (add)
6252 offset_addr = Rn + imm32;
6253 else
6254 offset_addr = Rn - imm32;
6255
6256 // address = if index then offset_addr else R[n];
6257 if (index)
6258 address = offset_addr;
6259 else
6260 address = Rn;
6261
6262 // R[t] = ZeroExtend(MemU[address,1], 32);
6263 RegisterInfo base_reg;
6264 RegisterInfo data_reg;
6265 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6266 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
6267
6268 EmulateInstruction::Context context;
6269 context.type = eContextRegisterLoad;
6270 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
6271
6272 uint64_t data = MemURead (context, address, 1, 0, &success);
6273 if (!success)
6274 return false;
6275
6276 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6277 return false;
6278
6279 // if wback then R[n] = offset_addr;
6280 if (wback)
6281 {
6282 context.type = eContextAdjustBaseRegister;
6283 context.SetAddress (offset_addr);
6284 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6285 return false;
6286 }
6287 }
6288 return true;
6289 }
6290
6291 // LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6292 // zero-extends it to form a 32-bit word and writes it to a register.
6293 bool
EmulateLDRBLiteral(const uint32_t opcode,const ARMEncoding encoding)6294 EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding)
6295 {
6296 #if 0
6297 if ConditionPassed() then
6298 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6299 base = Align(PC,4);
6300 address = if add then (base + imm32) else (base - imm32);
6301 R[t] = ZeroExtend(MemU[address,1], 32);
6302 #endif
6303
6304 bool success = false;
6305
6306 if (ConditionPassed(opcode))
6307 {
6308 uint32_t t;
6309 uint32_t imm32;
6310 bool add;
6311 switch (encoding)
6312 {
6313 case eEncodingT1:
6314 // if Rt == '1111' then SEE PLD;
6315 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6316 t = Bits32 (opcode, 15, 12);
6317 imm32 = Bits32 (opcode, 11, 0);
6318 add = BitIsSet (opcode, 23);
6319
6320 // if t == 13 then UNPREDICTABLE;
6321 if (t == 13)
6322 return false;
6323
6324 break;
6325
6326 case eEncodingA1:
6327 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6328 t = Bits32 (opcode, 15, 12);
6329 imm32 = Bits32 (opcode, 11, 0);
6330 add = BitIsSet (opcode, 23);
6331
6332 // if t == 15 then UNPREDICTABLE;
6333 if (t == 15)
6334 return false;
6335 break;
6336
6337 default:
6338 return false;
6339 }
6340
6341 // base = Align(PC,4);
6342 uint32_t pc_val = ReadCoreReg (PC_REG, &success);
6343 if (!success)
6344 return false;
6345
6346 uint32_t base = AlignPC (pc_val);
6347
6348 addr_t address;
6349 // address = if add then (base + imm32) else (base - imm32);
6350 if (add)
6351 address = base + imm32;
6352 else
6353 address = base - imm32;
6354
6355 // R[t] = ZeroExtend(MemU[address,1], 32);
6356 EmulateInstruction::Context context;
6357 context.type = eContextRelativeBranchImmediate;
6358 context.SetImmediate (address - base);
6359
6360 uint64_t data = MemURead (context, address, 1, 0, &success);
6361 if (!success)
6362 return false;
6363
6364 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6365 return false;
6366 }
6367 return true;
6368 }
6369
6370 // LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
6371 // memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6372 // optionally be shifted.
6373 bool
EmulateLDRBRegister(const uint32_t opcode,const ARMEncoding encoding)6374 EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding)
6375 {
6376 #if 0
6377 if ConditionPassed() then
6378 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6379 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6380 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6381 address = if index then offset_addr else R[n];
6382 R[t] = ZeroExtend(MemU[address,1],32);
6383 if wback then R[n] = offset_addr;
6384 #endif
6385
6386 bool success = false;
6387
6388 if (ConditionPassed(opcode))
6389 {
6390 uint32_t t;
6391 uint32_t n;
6392 uint32_t m;
6393 bool index;
6394 bool add;
6395 bool wback;
6396 ARM_ShifterType shift_t;
6397 uint32_t shift_n;
6398
6399 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6400 switch (encoding)
6401 {
6402 case eEncodingT1:
6403 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6404 t = Bits32 (opcode, 2, 0);
6405 n = Bits32 (opcode, 5, 3);
6406 m = Bits32 (opcode, 8, 6);
6407
6408 // index = TRUE; add = TRUE; wback = FALSE;
6409 index = true;
6410 add = true;
6411 wback = false;
6412
6413 // (shift_t, shift_n) = (SRType_LSL, 0);
6414 shift_t = SRType_LSL;
6415 shift_n = 0;
6416 break;
6417
6418 case eEncodingT2:
6419 // if Rt == '1111' then SEE PLD;
6420 // if Rn == '1111' then SEE LDRB (literal);
6421 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6422 t = Bits32 (opcode, 15, 12);
6423 n = Bits32 (opcode, 19, 16);
6424 m = Bits32 (opcode, 3, 0);
6425
6426 // index = TRUE; add = TRUE; wback = FALSE;
6427 index = true;
6428 add = true;
6429 wback = false;
6430
6431 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6432 shift_t = SRType_LSL;
6433 shift_n = Bits32 (opcode, 5, 4);
6434
6435 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6436 if ((t == 13) || BadReg (m))
6437 return false;
6438 break;
6439
6440 case eEncodingA1:
6441 {
6442 // if P == '0' && W == '1' then SEE LDRBT;
6443 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6444 t = Bits32 (opcode, 15, 12);
6445 n = Bits32 (opcode, 19, 16);
6446 m = Bits32 (opcode, 3, 0);
6447
6448 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
6449 index = BitIsSet (opcode, 24);
6450 add = BitIsSet (opcode, 23);
6451 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6452
6453 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6454 uint32_t type = Bits32 (opcode, 6, 5);
6455 uint32_t imm5 = Bits32 (opcode, 11, 7);
6456 shift_n = DecodeImmShift (type, imm5, shift_t);
6457
6458 // if t == 15 || m == 15 then UNPREDICTABLE;
6459 if ((t == 15) || (m == 15))
6460 return false;
6461
6462 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6463 if (wback && ((n == 15) || (n == t)))
6464 return false;
6465 }
6466 break;
6467
6468 default:
6469 return false;
6470 }
6471
6472 addr_t offset_addr;
6473 addr_t address;
6474
6475 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6476 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6477 if (!success)
6478 return false;
6479
6480 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
6481 if (!success)
6482 return false;
6483
6484 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6485 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6486 if (!success)
6487 return false;
6488
6489 if (add)
6490 offset_addr = Rn + offset;
6491 else
6492 offset_addr = Rn - offset;
6493
6494 // address = if index then offset_addr else R[n];
6495 if (index)
6496 address = offset_addr;
6497 else
6498 address = Rn;
6499
6500 // R[t] = ZeroExtend(MemU[address,1],32);
6501 RegisterInfo base_reg;
6502 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6503
6504 EmulateInstruction::Context context;
6505 context.type = eContextRegisterLoad;
6506 context.SetRegisterPlusOffset (base_reg, address - Rn);
6507
6508 uint64_t data = MemURead (context, address, 1, 0, &success);
6509 if (!success)
6510 return false;
6511
6512 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6513 return false;
6514
6515 // if wback then R[n] = offset_addr;
6516 if (wback)
6517 {
6518 context.type = eContextAdjustBaseRegister;
6519 context.SetAddress (offset_addr);
6520 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6521 return false;
6522 }
6523 }
6524 return true;
6525 }
6526
6527 // LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6528 // halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6529 // post-indexed, or pre-indexed addressing.
6530 bool
EmulateLDRHImmediate(const uint32_t opcode,const ARMEncoding encoding)6531 EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding)
6532 {
6533 #if 0
6534 if ConditionPassed() then
6535 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6536 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6537 address = if index then offset_addr else R[n];
6538 data = MemU[address,2];
6539 if wback then R[n] = offset_addr;
6540 if UnalignedSupport() || address<0> = '0' then
6541 R[t] = ZeroExtend(data, 32);
6542 else // Can only apply before ARMv7
6543 R[t] = bits(32) UNKNOWN;
6544 #endif
6545
6546
6547 bool success = false;
6548
6549 if (ConditionPassed(opcode))
6550 {
6551 uint32_t t;
6552 uint32_t n;
6553 uint32_t imm32;
6554 bool index;
6555 bool add;
6556 bool wback;
6557
6558 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6559 switch (encoding)
6560 {
6561 case eEncodingT1:
6562 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
6563 t = Bits32 (opcode, 2, 0);
6564 n = Bits32 (opcode, 5, 3);
6565 imm32 = Bits32 (opcode, 10, 6) << 1;
6566
6567 // index = TRUE; add = TRUE; wback = FALSE;
6568 index = true;
6569 add = true;
6570 wback = false;
6571
6572 break;
6573
6574 case eEncodingT2:
6575 // if Rt == '1111' then SEE "Unallocated memory hints";
6576 // if Rn == '1111' then SEE LDRH (literal);
6577 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6578 t = Bits32 (opcode, 15, 12);
6579 n = Bits32 (opcode, 19, 16);
6580 imm32 = Bits32 (opcode, 11, 0);
6581
6582 // index = TRUE; add = TRUE; wback = FALSE;
6583 index = true;
6584 add = true;
6585 wback = false;
6586
6587 // if t == 13 then UNPREDICTABLE;
6588 if (t == 13)
6589 return false;
6590 break;
6591
6592 case eEncodingT3:
6593 // if Rn == '1111' then SEE LDRH (literal);
6594 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
6595 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
6596 // if P == '0' && W == '0' then UNDEFINED;
6597 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6598 return false;
6599
6600 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6601 t = Bits32 (opcode, 15, 12);
6602 n = Bits32 (opcode, 19, 16);
6603 imm32 = Bits32 (opcode, 7, 0);
6604
6605 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
6606 index = BitIsSet (opcode, 10);
6607 add = BitIsSet (opcode, 9);
6608 wback = BitIsSet (opcode, 8);
6609
6610 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6611 if (BadReg (t) || (wback && (n == t)))
6612 return false;
6613 break;
6614
6615 default:
6616 return false;
6617 }
6618
6619 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6620 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6621 if (!success)
6622 return false;
6623
6624 addr_t offset_addr;
6625 addr_t address;
6626
6627 if (add)
6628 offset_addr = Rn + imm32;
6629 else
6630 offset_addr = Rn - imm32;
6631
6632 // address = if index then offset_addr else R[n];
6633 if (index)
6634 address = offset_addr;
6635 else
6636 address = Rn;
6637
6638 // data = MemU[address,2];
6639 RegisterInfo base_reg;
6640 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6641
6642 EmulateInstruction::Context context;
6643 context.type = eContextRegisterLoad;
6644 context.SetRegisterPlusOffset (base_reg, address - Rn);
6645
6646 uint64_t data = MemURead (context, address, 2, 0, &success);
6647 if (!success)
6648 return false;
6649
6650 // if wback then R[n] = offset_addr;
6651 if (wback)
6652 {
6653 context.type = eContextAdjustBaseRegister;
6654 context.SetAddress (offset_addr);
6655 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6656 return false;
6657 }
6658
6659 // if UnalignedSupport() || address<0> = '0' then
6660 if (UnalignedSupport () || BitIsClear (address, 0))
6661 {
6662 // R[t] = ZeroExtend(data, 32);
6663 context.type = eContextRegisterLoad;
6664 context.SetRegisterPlusOffset (base_reg, address - Rn);
6665 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6666 return false;
6667 }
6668 else // Can only apply before ARMv7
6669 {
6670 // R[t] = bits(32) UNKNOWN;
6671 WriteBits32Unknown (t);
6672 }
6673 }
6674 return true;
6675 }
6676
6677 // LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6678 // zero-extends it to form a 32-bit word, and writes it to a register.
6679 bool
EmulateLDRHLiteral(const uint32_t opcode,const ARMEncoding encoding)6680 EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding)
6681 {
6682 #if 0
6683 if ConditionPassed() then
6684 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6685 base = Align(PC,4);
6686 address = if add then (base + imm32) else (base - imm32);
6687 data = MemU[address,2];
6688 if UnalignedSupport() || address<0> = '0' then
6689 R[t] = ZeroExtend(data, 32);
6690 else // Can only apply before ARMv7
6691 R[t] = bits(32) UNKNOWN;
6692 #endif
6693
6694 bool success = false;
6695
6696 if (ConditionPassed(opcode))
6697 {
6698 uint32_t t;
6699 uint32_t imm32;
6700 bool add;
6701
6702 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6703 switch (encoding)
6704 {
6705 case eEncodingT1:
6706 // if Rt == '1111' then SEE "Unallocated memory hints";
6707 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6708 t = Bits32 (opcode, 15, 12);
6709 imm32 = Bits32 (opcode, 11, 0);
6710 add = BitIsSet (opcode, 23);
6711
6712 // if t == 13 then UNPREDICTABLE;
6713 if (t == 13)
6714 return false;
6715
6716 break;
6717
6718 case eEncodingA1:
6719 {
6720 uint32_t imm4H = Bits32 (opcode, 11, 8);
6721 uint32_t imm4L = Bits32 (opcode, 3, 0);
6722
6723 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
6724 t = Bits32 (opcode, 15, 12);
6725 imm32 = (imm4H << 4) | imm4L;
6726 add = BitIsSet (opcode, 23);
6727
6728 // if t == 15 then UNPREDICTABLE;
6729 if (t == 15)
6730 return false;
6731 break;
6732 }
6733
6734 default:
6735 return false;
6736 }
6737
6738 // base = Align(PC,4);
6739 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
6740 if (!success)
6741 return false;
6742
6743 addr_t base = AlignPC (pc_value);
6744 addr_t address;
6745
6746 // address = if add then (base + imm32) else (base - imm32);
6747 if (add)
6748 address = base + imm32;
6749 else
6750 address = base - imm32;
6751
6752 // data = MemU[address,2];
6753 RegisterInfo base_reg;
6754 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
6755
6756 EmulateInstruction::Context context;
6757 context.type = eContextRegisterLoad;
6758 context.SetRegisterPlusOffset (base_reg, address - base);
6759
6760 uint64_t data = MemURead (context, address, 2, 0, &success);
6761 if (!success)
6762 return false;
6763
6764
6765 // if UnalignedSupport() || address<0> = '0' then
6766 if (UnalignedSupport () || BitIsClear (address, 0))
6767 {
6768 // R[t] = ZeroExtend(data, 32);
6769 context.type = eContextRegisterLoad;
6770 context.SetRegisterPlusOffset (base_reg, address - base);
6771 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6772 return false;
6773
6774 }
6775 else // Can only apply before ARMv7
6776 {
6777 // R[t] = bits(32) UNKNOWN;
6778 WriteBits32Unknown (t);
6779 }
6780 }
6781 return true;
6782 }
6783
6784 // LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6785 // from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6786 // be shifted left by 0, 1, 2, or 3 bits.
6787 bool
EmulateLDRHRegister(const uint32_t opcode,const ARMEncoding encoding)6788 EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding)
6789 {
6790 #if 0
6791 if ConditionPassed() then
6792 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6793 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6794 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6795 address = if index then offset_addr else R[n];
6796 data = MemU[address,2];
6797 if wback then R[n] = offset_addr;
6798 if UnalignedSupport() || address<0> = '0' then
6799 R[t] = ZeroExtend(data, 32);
6800 else // Can only apply before ARMv7
6801 R[t] = bits(32) UNKNOWN;
6802 #endif
6803
6804 bool success = false;
6805
6806 if (ConditionPassed(opcode))
6807 {
6808 uint32_t t;
6809 uint32_t n;
6810 uint32_t m;
6811 bool index;
6812 bool add;
6813 bool wback;
6814 ARM_ShifterType shift_t;
6815 uint32_t shift_n;
6816
6817 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6818 switch (encoding)
6819 {
6820 case eEncodingT1:
6821 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6822 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6823 t = Bits32 (opcode, 2, 0);
6824 n = Bits32 (opcode, 5, 3);
6825 m = Bits32 (opcode, 8, 6);
6826
6827 // index = TRUE; add = TRUE; wback = FALSE;
6828 index = true;
6829 add = true;
6830 wback = false;
6831
6832 // (shift_t, shift_n) = (SRType_LSL, 0);
6833 shift_t = SRType_LSL;
6834 shift_n = 0;
6835
6836 break;
6837
6838 case eEncodingT2:
6839 // if Rn == '1111' then SEE LDRH (literal);
6840 // if Rt == '1111' then SEE "Unallocated memory hints";
6841 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6842 t = Bits32 (opcode, 15, 12);
6843 n = Bits32 (opcode, 19, 16);
6844 m = Bits32 (opcode, 3, 0);
6845
6846 // index = TRUE; add = TRUE; wback = FALSE;
6847 index = true;
6848 add = true;
6849 wback = false;
6850
6851 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6852 shift_t = SRType_LSL;
6853 shift_n = Bits32 (opcode, 5, 4);
6854
6855 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6856 if ((t == 13) || BadReg (m))
6857 return false;
6858 break;
6859
6860 case eEncodingA1:
6861 // if P == '0' && W == '1' then SEE LDRHT;
6862 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6863 t = Bits32 (opcode, 15, 12);
6864 n = Bits32 (opcode, 19, 16);
6865 m = Bits32 (opcode, 3, 0);
6866
6867 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
6868 index = BitIsSet (opcode, 24);
6869 add = BitIsSet (opcode, 23);
6870 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6871
6872 // (shift_t, shift_n) = (SRType_LSL, 0);
6873 shift_t = SRType_LSL;
6874 shift_n = 0;
6875
6876 // if t == 15 || m == 15 then UNPREDICTABLE;
6877 if ((t == 15) || (m == 15))
6878 return false;
6879
6880 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6881 if (wback && ((n == 15) || (n == t)))
6882 return false;
6883
6884 break;
6885
6886 default:
6887 return false;
6888 }
6889
6890 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6891
6892 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6893 if (!success)
6894 return false;
6895
6896 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
6897 if (!success)
6898 return false;
6899
6900 addr_t offset_addr;
6901 addr_t address;
6902
6903 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6904 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6905 if (!success)
6906 return false;
6907
6908 if (add)
6909 offset_addr = Rn + offset;
6910 else
6911 offset_addr = Rn - offset;
6912
6913 // address = if index then offset_addr else R[n];
6914 if (index)
6915 address = offset_addr;
6916 else
6917 address = Rn;
6918
6919 // data = MemU[address,2];
6920 RegisterInfo base_reg;
6921 RegisterInfo offset_reg;
6922 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6923 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
6924
6925 EmulateInstruction::Context context;
6926 context.type = eContextRegisterLoad;
6927 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6928 uint64_t data = MemURead (context, address, 2, 0, &success);
6929 if (!success)
6930 return false;
6931
6932 // if wback then R[n] = offset_addr;
6933 if (wback)
6934 {
6935 context.type = eContextAdjustBaseRegister;
6936 context.SetAddress (offset_addr);
6937 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6938 return false;
6939 }
6940
6941 // if UnalignedSupport() || address<0> = '0' then
6942 if (UnalignedSupport() || BitIsClear (address, 0))
6943 {
6944 // R[t] = ZeroExtend(data, 32);
6945 context.type = eContextRegisterLoad;
6946 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6947 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6948 return false;
6949 }
6950 else // Can only apply before ARMv7
6951 {
6952 // R[t] = bits(32) UNKNOWN;
6953 WriteBits32Unknown (t);
6954 }
6955 }
6956 return true;
6957 }
6958
6959 // LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6960 // memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6961 // or pre-indexed addressing.
6962 bool
EmulateLDRSBImmediate(const uint32_t opcode,const ARMEncoding encoding)6963 EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding)
6964 {
6965 #if 0
6966 if ConditionPassed() then
6967 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6968 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6969 address = if index then offset_addr else R[n];
6970 R[t] = SignExtend(MemU[address,1], 32);
6971 if wback then R[n] = offset_addr;
6972 #endif
6973
6974 bool success = false;
6975
6976 if (ConditionPassed(opcode))
6977 {
6978 uint32_t t;
6979 uint32_t n;
6980 uint32_t imm32;
6981 bool index;
6982 bool add;
6983 bool wback;
6984
6985 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6986 switch (encoding)
6987 {
6988 case eEncodingT1:
6989 // if Rt == '1111' then SEE PLI;
6990 // if Rn == '1111' then SEE LDRSB (literal);
6991 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6992 t = Bits32 (opcode, 15, 12);
6993 n = Bits32 (opcode, 19, 16);
6994 imm32 = Bits32 (opcode, 11, 0);
6995
6996 // index = TRUE; add = TRUE; wback = FALSE;
6997 index = true;
6998 add = true;
6999 wback = false;
7000
7001 // if t == 13 then UNPREDICTABLE;
7002 if (t == 13)
7003 return false;
7004
7005 break;
7006
7007 case eEncodingT2:
7008 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
7009 // if Rn == '1111' then SEE LDRSB (literal);
7010 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
7011 // if P == '0' && W == '0' then UNDEFINED;
7012 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7013 return false;
7014
7015 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7016 t = Bits32 (opcode, 15, 12);
7017 n = Bits32 (opcode, 19, 16);
7018 imm32 = Bits32 (opcode, 7, 0);
7019
7020 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7021 index = BitIsSet (opcode, 10);
7022 add = BitIsSet (opcode, 9);
7023 wback = BitIsSet (opcode, 8);
7024
7025 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7026 if (((t == 13) || ((t == 15)
7027 && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8))))
7028 || (wback && (n == t)))
7029 return false;
7030
7031 break;
7032
7033 case eEncodingA1:
7034 {
7035 // if Rn == '1111' then SEE LDRSB (literal);
7036 // if P == '0' && W == '1' then SEE LDRSBT;
7037 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7038 t = Bits32 (opcode, 15, 12);
7039 n = Bits32 (opcode, 19, 16);
7040
7041 uint32_t imm4H = Bits32 (opcode, 11, 8);
7042 uint32_t imm4L = Bits32 (opcode, 3, 0);
7043 imm32 = (imm4H << 4) | imm4L;
7044
7045 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
7046 index = BitIsSet (opcode, 24);
7047 add = BitIsSet (opcode, 23);
7048 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
7049
7050 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7051 if ((t == 15) || (wback && (n == t)))
7052 return false;
7053
7054 break;
7055 }
7056
7057 default:
7058 return false;
7059 }
7060
7061 uint64_t Rn = ReadCoreReg (n, &success);
7062 if (!success)
7063 return false;
7064
7065 addr_t offset_addr;
7066 addr_t address;
7067
7068 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7069 if (add)
7070 offset_addr = Rn + imm32;
7071 else
7072 offset_addr = Rn - imm32;
7073
7074 // address = if index then offset_addr else R[n];
7075 if (index)
7076 address = offset_addr;
7077 else
7078 address = Rn;
7079
7080 // R[t] = SignExtend(MemU[address,1], 32);
7081 RegisterInfo base_reg;
7082 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7083
7084 EmulateInstruction::Context context;
7085 context.type = eContextRegisterLoad;
7086 context.SetRegisterPlusOffset (base_reg, address - Rn);
7087
7088 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7089 if (!success)
7090 return false;
7091
7092 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7093 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7094 return false;
7095
7096 // if wback then R[n] = offset_addr;
7097 if (wback)
7098 {
7099 context.type = eContextAdjustBaseRegister;
7100 context.SetAddress (offset_addr);
7101 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7102 return false;
7103 }
7104 }
7105
7106 return true;
7107 }
7108
7109 // LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
7110 // sign-extends it to form a 32-bit word, and writes tit to a register.
7111 bool
EmulateLDRSBLiteral(const uint32_t opcode,const ARMEncoding encoding)7112 EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding)
7113 {
7114 #if 0
7115 if ConditionPassed() then
7116 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7117 base = Align(PC,4);
7118 address = if add then (base + imm32) else (base - imm32);
7119 R[t] = SignExtend(MemU[address,1], 32);
7120 #endif
7121
7122 bool success = false;
7123
7124 if (ConditionPassed(opcode))
7125 {
7126 uint32_t t;
7127 uint32_t imm32;
7128 bool add;
7129
7130 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7131 switch (encoding)
7132 {
7133 case eEncodingT1:
7134 // if Rt == '1111' then SEE PLI;
7135 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
7136 t = Bits32 (opcode, 15, 12);
7137 imm32 = Bits32 (opcode, 11, 0);
7138 add = BitIsSet (opcode, 23);
7139
7140 // if t == 13 then UNPREDICTABLE;
7141 if (t == 13)
7142 return false;
7143
7144 break;
7145
7146 case eEncodingA1:
7147 {
7148 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7149 t = Bits32 (opcode, 15, 12);
7150 uint32_t imm4H = Bits32 (opcode, 11, 8);
7151 uint32_t imm4L = Bits32 (opcode, 3, 0);
7152 imm32 = (imm4H << 4) | imm4L;
7153 add = BitIsSet (opcode, 23);
7154
7155 // if t == 15 then UNPREDICTABLE;
7156 if (t == 15)
7157 return false;
7158
7159 break;
7160 }
7161
7162 default:
7163 return false;
7164 }
7165
7166 // base = Align(PC,4);
7167 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
7168 if (!success)
7169 return false;
7170 uint64_t base = AlignPC (pc_value);
7171
7172 // address = if add then (base + imm32) else (base - imm32);
7173 addr_t address;
7174 if (add)
7175 address = base + imm32;
7176 else
7177 address = base - imm32;
7178
7179 // R[t] = SignExtend(MemU[address,1], 32);
7180 RegisterInfo base_reg;
7181 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
7182
7183 EmulateInstruction::Context context;
7184 context.type = eContextRegisterLoad;
7185 context.SetRegisterPlusOffset (base_reg, address - base);
7186
7187 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7188 if (!success)
7189 return false;
7190
7191 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7192 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7193 return false;
7194 }
7195 return true;
7196 }
7197
7198 // LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
7199 // memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7200 // shifted left by 0, 1, 2, or 3 bits.
7201 bool
EmulateLDRSBRegister(const uint32_t opcode,const ARMEncoding encoding)7202 EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding)
7203 {
7204 #if 0
7205 if ConditionPassed() then
7206 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7207 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7208 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7209 address = if index then offset_addr else R[n];
7210 R[t] = SignExtend(MemU[address,1], 32);
7211 if wback then R[n] = offset_addr;
7212 #endif
7213
7214 bool success = false;
7215
7216 if (ConditionPassed(opcode))
7217 {
7218 uint32_t t;
7219 uint32_t n;
7220 uint32_t m;
7221 bool index;
7222 bool add;
7223 bool wback;
7224 ARM_ShifterType shift_t;
7225 uint32_t shift_n;
7226
7227 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7228 switch (encoding)
7229 {
7230 case eEncodingT1:
7231 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7232 t = Bits32 (opcode, 2, 0);
7233 n = Bits32 (opcode, 5, 3);
7234 m = Bits32 (opcode, 8, 6);
7235
7236 // index = TRUE; add = TRUE; wback = FALSE;
7237 index = true;
7238 add = true;
7239 wback = false;
7240
7241 // (shift_t, shift_n) = (SRType_LSL, 0);
7242 shift_t = SRType_LSL;
7243 shift_n = 0;
7244
7245 break;
7246
7247 case eEncodingT2:
7248 // if Rt == '1111' then SEE PLI;
7249 // if Rn == '1111' then SEE LDRSB (literal);
7250 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7251 t = Bits32 (opcode, 15, 12);
7252 n = Bits32 (opcode, 19, 16);
7253 m = Bits32 (opcode, 3, 0);
7254
7255 // index = TRUE; add = TRUE; wback = FALSE;
7256 index = true;
7257 add = true;
7258 wback = false;
7259
7260 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7261 shift_t = SRType_LSL;
7262 shift_n = Bits32 (opcode, 5, 4);
7263
7264 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7265 if ((t == 13) || BadReg (m))
7266 return false;
7267 break;
7268
7269 case eEncodingA1:
7270 // if P == '0' && W == '1' then SEE LDRSBT;
7271 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7272 t = Bits32 (opcode, 15, 12);
7273 n = Bits32 (opcode, 19, 16);
7274 m = Bits32 (opcode, 3, 0);
7275
7276 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
7277 index = BitIsSet (opcode, 24);
7278 add = BitIsSet (opcode, 23);
7279 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7280
7281 // (shift_t, shift_n) = (SRType_LSL, 0);
7282 shift_t = SRType_LSL;
7283 shift_n = 0;
7284
7285 // if t == 15 || m == 15 then UNPREDICTABLE;
7286 if ((t == 15) || (m == 15))
7287 return false;
7288
7289 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7290 if (wback && ((n == 15) || (n == t)))
7291 return false;
7292 break;
7293
7294 default:
7295 return false;
7296 }
7297
7298 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7299 if (!success)
7300 return false;
7301
7302 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7303 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
7304 if (!success)
7305 return false;
7306
7307 addr_t offset_addr;
7308 addr_t address;
7309
7310 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7311 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7312 if (!success)
7313 return false;
7314
7315 if (add)
7316 offset_addr = Rn + offset;
7317 else
7318 offset_addr = Rn - offset;
7319
7320 // address = if index then offset_addr else R[n];
7321 if (index)
7322 address = offset_addr;
7323 else
7324 address = Rn;
7325
7326 // R[t] = SignExtend(MemU[address,1], 32);
7327 RegisterInfo base_reg;
7328 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7329 RegisterInfo offset_reg;
7330 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
7331
7332 EmulateInstruction::Context context;
7333 context.type = eContextRegisterLoad;
7334 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7335
7336 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7337 if (!success)
7338 return false;
7339
7340 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7341 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7342 return false;
7343
7344 // if wback then R[n] = offset_addr;
7345 if (wback)
7346 {
7347 context.type = eContextAdjustBaseRegister;
7348 context.SetAddress (offset_addr);
7349 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7350 return false;
7351 }
7352 }
7353 return true;
7354 }
7355
7356 // LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
7357 // memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
7358 // pre-indexed addressing.
7359 bool
EmulateLDRSHImmediate(const uint32_t opcode,const ARMEncoding encoding)7360 EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding)
7361 {
7362 #if 0
7363 if ConditionPassed() then
7364 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7365 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7366 address = if index then offset_addr else R[n];
7367 data = MemU[address,2];
7368 if wback then R[n] = offset_addr;
7369 if UnalignedSupport() || address<0> = '0' then
7370 R[t] = SignExtend(data, 32);
7371 else // Can only apply before ARMv7
7372 R[t] = bits(32) UNKNOWN;
7373 #endif
7374
7375 bool success = false;
7376
7377 if (ConditionPassed(opcode))
7378 {
7379 uint32_t t;
7380 uint32_t n;
7381 uint32_t imm32;
7382 bool index;
7383 bool add;
7384 bool wback;
7385
7386 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7387 switch (encoding)
7388 {
7389 case eEncodingT1:
7390 // if Rn == '1111' then SEE LDRSH (literal);
7391 // if Rt == '1111' then SEE "Unallocated memory hints";
7392 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7393 t = Bits32 (opcode, 15, 12);
7394 n = Bits32 (opcode, 19, 16);
7395 imm32 = Bits32 (opcode, 11, 0);
7396
7397 // index = TRUE; add = TRUE; wback = FALSE;
7398 index = true;
7399 add = true;
7400 wback = false;
7401
7402 // if t == 13 then UNPREDICTABLE;
7403 if (t == 13)
7404 return false;
7405
7406 break;
7407
7408 case eEncodingT2:
7409 // if Rn == '1111' then SEE LDRSH (literal);
7410 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
7411 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7412 // if P == '0' && W == '0' then UNDEFINED;
7413 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7414 return false;
7415
7416 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7417 t = Bits32 (opcode, 15, 12);
7418 n = Bits32 (opcode, 19, 16);
7419 imm32 = Bits32 (opcode, 7, 0);
7420
7421 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7422 index = BitIsSet (opcode, 10);
7423 add = BitIsSet (opcode, 9);
7424 wback = BitIsSet (opcode, 8);
7425
7426 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7427 if (BadReg (t) || (wback && (n == t)))
7428 return false;
7429
7430 break;
7431
7432 case eEncodingA1:
7433 {
7434 // if Rn == '1111' then SEE LDRSH (literal);
7435 // if P == '0' && W == '1' then SEE LDRSHT;
7436 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7437 t = Bits32 (opcode, 15, 12);
7438 n = Bits32 (opcode, 19, 16);
7439 uint32_t imm4H = Bits32 (opcode, 11,8);
7440 uint32_t imm4L = Bits32 (opcode, 3, 0);
7441 imm32 = (imm4H << 4) | imm4L;
7442
7443 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
7444 index = BitIsSet (opcode, 24);
7445 add = BitIsSet (opcode, 23);
7446 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7447
7448 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7449 if ((t == 15) || (wback && (n == t)))
7450 return false;
7451
7452 break;
7453 }
7454
7455 default:
7456 return false;
7457 }
7458
7459 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7460 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7461 if (!success)
7462 return false;
7463
7464 addr_t offset_addr;
7465 if (add)
7466 offset_addr = Rn + imm32;
7467 else
7468 offset_addr = Rn - imm32;
7469
7470 // address = if index then offset_addr else R[n];
7471 addr_t address;
7472 if (index)
7473 address = offset_addr;
7474 else
7475 address = Rn;
7476
7477 // data = MemU[address,2];
7478 RegisterInfo base_reg;
7479 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7480
7481 EmulateInstruction::Context context;
7482 context.type = eContextRegisterLoad;
7483 context.SetRegisterPlusOffset (base_reg, address - Rn);
7484
7485 uint64_t data = MemURead (context, address, 2, 0, &success);
7486 if (!success)
7487 return false;
7488
7489 // if wback then R[n] = offset_addr;
7490 if (wback)
7491 {
7492 context.type = eContextAdjustBaseRegister;
7493 context.SetAddress (offset_addr);
7494 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7495 return false;
7496 }
7497
7498 // if UnalignedSupport() || address<0> = '0' then
7499 if (UnalignedSupport() || BitIsClear (address, 0))
7500 {
7501 // R[t] = SignExtend(data, 32);
7502 int64_t signed_data = llvm::SignExtend64<16>(data);
7503 context.type = eContextRegisterLoad;
7504 context.SetRegisterPlusOffset (base_reg, address - Rn);
7505 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7506 return false;
7507 }
7508 else // Can only apply before ARMv7
7509 {
7510 // R[t] = bits(32) UNKNOWN;
7511 WriteBits32Unknown (t);
7512 }
7513 }
7514 return true;
7515 }
7516
7517 // LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7518 // sign-extends it to from a 32-bit word, and writes it to a register.
7519 bool
EmulateLDRSHLiteral(const uint32_t opcode,const ARMEncoding encoding)7520 EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding)
7521 {
7522 #if 0
7523 if ConditionPassed() then
7524 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7525 base = Align(PC,4);
7526 address = if add then (base + imm32) else (base - imm32);
7527 data = MemU[address,2];
7528 if UnalignedSupport() || address<0> = '0' then
7529 R[t] = SignExtend(data, 32);
7530 else // Can only apply before ARMv7
7531 R[t] = bits(32) UNKNOWN;
7532 #endif
7533
7534 bool success = false;
7535
7536 if (ConditionPassed(opcode))
7537 {
7538 uint32_t t;
7539 uint32_t imm32;
7540 bool add;
7541
7542 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7543 switch (encoding)
7544 {
7545 case eEncodingT1:
7546 // if Rt == '1111' then SEE "Unallocated memory hints";
7547 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
7548 t = Bits32 (opcode, 15, 12);
7549 imm32 = Bits32 (opcode, 11, 0);
7550 add = BitIsSet (opcode, 23);
7551
7552 // if t == 13 then UNPREDICTABLE;
7553 if (t == 13)
7554 return false;
7555
7556 break;
7557
7558 case eEncodingA1:
7559 {
7560 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7561 t = Bits32 (opcode, 15, 12);
7562 uint32_t imm4H = Bits32 (opcode, 11, 8);
7563 uint32_t imm4L = Bits32 (opcode, 3, 0);
7564 imm32 = (imm4H << 4) | imm4L;
7565 add = BitIsSet (opcode, 23);
7566
7567 // if t == 15 then UNPREDICTABLE;
7568 if (t == 15)
7569 return false;
7570
7571 break;
7572 }
7573 default:
7574 return false;
7575 }
7576
7577 // base = Align(PC,4);
7578 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
7579 if (!success)
7580 return false;
7581
7582 uint64_t base = AlignPC (pc_value);
7583
7584 addr_t address;
7585 // address = if add then (base + imm32) else (base - imm32);
7586 if (add)
7587 address = base + imm32;
7588 else
7589 address = base - imm32;
7590
7591 // data = MemU[address,2];
7592 RegisterInfo base_reg;
7593 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
7594
7595 EmulateInstruction::Context context;
7596 context.type = eContextRegisterLoad;
7597 context.SetRegisterPlusOffset (base_reg, imm32);
7598
7599 uint64_t data = MemURead (context, address, 2, 0, &success);
7600 if (!success)
7601 return false;
7602
7603 // if UnalignedSupport() || address<0> = '0' then
7604 if (UnalignedSupport() || BitIsClear (address, 0))
7605 {
7606 // R[t] = SignExtend(data, 32);
7607 int64_t signed_data = llvm::SignExtend64<16>(data);
7608 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7609 return false;
7610 }
7611 else // Can only apply before ARMv7
7612 {
7613 // R[t] = bits(32) UNKNOWN;
7614 WriteBits32Unknown (t);
7615 }
7616 }
7617 return true;
7618 }
7619
7620 // LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7621 // from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7622 // shifted left by 0, 1, 2, or 3 bits.
7623 bool
EmulateLDRSHRegister(const uint32_t opcode,const ARMEncoding encoding)7624 EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding)
7625 {
7626 #if 0
7627 if ConditionPassed() then
7628 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7629 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7630 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7631 address = if index then offset_addr else R[n];
7632 data = MemU[address,2];
7633 if wback then R[n] = offset_addr;
7634 if UnalignedSupport() || address<0> = '0' then
7635 R[t] = SignExtend(data, 32);
7636 else // Can only apply before ARMv7
7637 R[t] = bits(32) UNKNOWN;
7638 #endif
7639
7640 bool success = false;
7641
7642 if (ConditionPassed(opcode))
7643 {
7644 uint32_t t;
7645 uint32_t n;
7646 uint32_t m;
7647 bool index;
7648 bool add;
7649 bool wback;
7650 ARM_ShifterType shift_t;
7651 uint32_t shift_n;
7652
7653 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7654 switch (encoding)
7655 {
7656 case eEncodingT1:
7657 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7658 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7659 t = Bits32 (opcode, 2, 0);
7660 n = Bits32 (opcode, 5, 3);
7661 m = Bits32 (opcode, 8, 6);
7662
7663 // index = TRUE; add = TRUE; wback = FALSE;
7664 index = true;
7665 add = true;
7666 wback = false;
7667
7668 // (shift_t, shift_n) = (SRType_LSL, 0);
7669 shift_t = SRType_LSL;
7670 shift_n = 0;
7671
7672 break;
7673
7674 case eEncodingT2:
7675 // if Rn == '1111' then SEE LDRSH (literal);
7676 // if Rt == '1111' then SEE "Unallocated memory hints";
7677 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7678 t = Bits32 (opcode, 15, 12);
7679 n = Bits32 (opcode, 19, 16);
7680 m = Bits32 (opcode, 3, 0);
7681
7682 // index = TRUE; add = TRUE; wback = FALSE;
7683 index = true;
7684 add = true;
7685 wback = false;
7686
7687 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7688 shift_t = SRType_LSL;
7689 shift_n = Bits32 (opcode, 5, 4);
7690
7691 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7692 if ((t == 13) || BadReg (m))
7693 return false;
7694
7695 break;
7696
7697 case eEncodingA1:
7698 // if P == '0' && W == '1' then SEE LDRSHT;
7699 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7700 t = Bits32 (opcode, 15, 12);
7701 n = Bits32 (opcode, 19, 16);
7702 m = Bits32 (opcode, 3, 0);
7703
7704 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
7705 index = BitIsSet (opcode, 24);
7706 add = BitIsSet (opcode, 23);
7707 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7708
7709 // (shift_t, shift_n) = (SRType_LSL, 0);
7710 shift_t = SRType_LSL;
7711 shift_n = 0;
7712
7713 // if t == 15 || m == 15 then UNPREDICTABLE;
7714 if ((t == 15) || (m == 15))
7715 return false;
7716
7717 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7718 if (wback && ((n == 15) || (n == t)))
7719 return false;
7720
7721 break;
7722
7723 default:
7724 return false;
7725 }
7726
7727 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7728 if (!success)
7729 return false;
7730
7731 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7732 if (!success)
7733 return false;
7734
7735 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7736 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
7737 if (!success)
7738 return false;
7739
7740 addr_t offset_addr;
7741 addr_t address;
7742
7743 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7744 if (add)
7745 offset_addr = Rn + offset;
7746 else
7747 offset_addr = Rn - offset;
7748
7749 // address = if index then offset_addr else R[n];
7750 if (index)
7751 address = offset_addr;
7752 else
7753 address = Rn;
7754
7755 // data = MemU[address,2];
7756 RegisterInfo base_reg;
7757 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7758
7759 RegisterInfo offset_reg;
7760 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
7761
7762 EmulateInstruction::Context context;
7763 context.type = eContextRegisterLoad;
7764 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7765
7766 uint64_t data = MemURead (context, address, 2, 0, &success);
7767 if (!success)
7768 return false;
7769
7770 // if wback then R[n] = offset_addr;
7771 if (wback)
7772 {
7773 context.type = eContextAdjustBaseRegister;
7774 context.SetAddress (offset_addr);
7775 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7776 return false;
7777 }
7778
7779 // if UnalignedSupport() || address<0> = '0' then
7780 if (UnalignedSupport() || BitIsClear (address, 0))
7781 {
7782 // R[t] = SignExtend(data, 32);
7783 context.type = eContextRegisterLoad;
7784 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7785
7786 int64_t signed_data = llvm::SignExtend64<16>(data);
7787 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7788 return false;
7789 }
7790 else // Can only apply before ARMv7
7791 {
7792 // R[t] = bits(32) UNKNOWN;
7793 WriteBits32Unknown (t);
7794 }
7795 }
7796 return true;
7797 }
7798
7799 // SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7800 // register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7801 bool
EmulateSXTB(const uint32_t opcode,const ARMEncoding encoding)7802 EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding)
7803 {
7804 #if 0
7805 if ConditionPassed() then
7806 EncodingSpecificOperations();
7807 rotated = ROR(R[m], rotation);
7808 R[d] = SignExtend(rotated<7:0>, 32);
7809 #endif
7810
7811 bool success = false;
7812
7813 if (ConditionPassed(opcode))
7814 {
7815 uint32_t d;
7816 uint32_t m;
7817 uint32_t rotation;
7818
7819 // EncodingSpecificOperations();
7820 switch (encoding)
7821 {
7822 case eEncodingT1:
7823 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7824 d = Bits32 (opcode, 2, 0);
7825 m = Bits32 (opcode, 5, 3);
7826 rotation = 0;
7827
7828 break;
7829
7830 case eEncodingT2:
7831 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
7832 d = Bits32 (opcode, 11, 8);
7833 m = Bits32 (opcode, 3, 0);
7834 rotation = Bits32 (opcode, 5, 4) << 3;
7835
7836 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7837 if (BadReg (d) || BadReg (m))
7838 return false;
7839
7840 break;
7841
7842 case eEncodingA1:
7843 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
7844 d = Bits32 (opcode, 15, 12);
7845 m = Bits32 (opcode, 3, 0);
7846 rotation = Bits32 (opcode, 11, 10) << 3;
7847
7848 // if d == 15 || m == 15 then UNPREDICTABLE;
7849 if ((d == 15) || (m == 15))
7850 return false;
7851
7852 break;
7853
7854 default:
7855 return false;
7856 }
7857
7858 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7859 if (!success)
7860 return false;
7861
7862 // rotated = ROR(R[m], rotation);
7863 uint64_t rotated = ROR (Rm, rotation, &success);
7864 if (!success)
7865 return false;
7866
7867 // R[d] = SignExtend(rotated<7:0>, 32);
7868 int64_t data = llvm::SignExtend64<8>(rotated);
7869
7870 RegisterInfo source_reg;
7871 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
7872
7873 EmulateInstruction::Context context;
7874 context.type = eContextRegisterLoad;
7875 context.SetRegister (source_reg);
7876
7877 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
7878 return false;
7879 }
7880 return true;
7881 }
7882
7883 // SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7884 // register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7885 bool
EmulateSXTH(const uint32_t opcode,const ARMEncoding encoding)7886 EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding)
7887 {
7888 #if 0
7889 if ConditionPassed() then
7890 EncodingSpecificOperations();
7891 rotated = ROR(R[m], rotation);
7892 R[d] = SignExtend(rotated<15:0>, 32);
7893 #endif
7894
7895 bool success = false;
7896
7897 if (ConditionPassed(opcode))
7898 {
7899 uint32_t d;
7900 uint32_t m;
7901 uint32_t rotation;
7902
7903 // EncodingSpecificOperations();
7904 switch (encoding)
7905 {
7906 case eEncodingT1:
7907 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7908 d = Bits32 (opcode, 2, 0);
7909 m = Bits32 (opcode, 5, 3);
7910 rotation = 0;
7911
7912 break;
7913
7914 case eEncodingT2:
7915 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
7916 d = Bits32 (opcode, 11, 8);
7917 m = Bits32 (opcode, 3, 0);
7918 rotation = Bits32 (opcode, 5, 4) << 3;
7919
7920 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7921 if (BadReg (d) || BadReg (m))
7922 return false;
7923
7924 break;
7925
7926 case eEncodingA1:
7927 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
7928 d = Bits32 (opcode, 15, 12);
7929 m = Bits32 (opcode, 3, 0);
7930 rotation = Bits32 (opcode, 11, 10) << 3;
7931
7932 // if d == 15 || m == 15 then UNPREDICTABLE;
7933 if ((d == 15) || (m == 15))
7934 return false;
7935
7936 break;
7937
7938 default:
7939 return false;
7940 }
7941
7942 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7943 if (!success)
7944 return false;
7945
7946 // rotated = ROR(R[m], rotation);
7947 uint64_t rotated = ROR (Rm, rotation, &success);
7948 if (!success)
7949 return false;
7950
7951 // R[d] = SignExtend(rotated<15:0>, 32);
7952 RegisterInfo source_reg;
7953 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
7954
7955 EmulateInstruction::Context context;
7956 context.type = eContextRegisterLoad;
7957 context.SetRegister (source_reg);
7958
7959 int64_t data = llvm::SignExtend64<16> (rotated);
7960 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
7961 return false;
7962 }
7963
7964 return true;
7965 }
7966
7967 // UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7968 // register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7969 bool
EmulateUXTB(const uint32_t opcode,const ARMEncoding encoding)7970 EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding)
7971 {
7972 #if 0
7973 if ConditionPassed() then
7974 EncodingSpecificOperations();
7975 rotated = ROR(R[m], rotation);
7976 R[d] = ZeroExtend(rotated<7:0>, 32);
7977 #endif
7978
7979 bool success = false;
7980
7981 if (ConditionPassed(opcode))
7982 {
7983 uint32_t d;
7984 uint32_t m;
7985 uint32_t rotation;
7986
7987 // EncodingSpecificOperations();
7988 switch (encoding)
7989 {
7990 case eEncodingT1:
7991 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7992 d = Bits32 (opcode, 2, 0);
7993 m = Bits32 (opcode, 5, 3);
7994 rotation = 0;
7995
7996 break;
7997
7998 case eEncodingT2:
7999 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8000 d = Bits32 (opcode, 11, 8);
8001 m = Bits32 (opcode, 3, 0);
8002 rotation = Bits32 (opcode, 5, 4) << 3;
8003
8004 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8005 if (BadReg (d) || BadReg (m))
8006 return false;
8007
8008 break;
8009
8010 case eEncodingA1:
8011 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8012 d = Bits32 (opcode, 15, 12);
8013 m = Bits32 (opcode, 3, 0);
8014 rotation = Bits32 (opcode, 11, 10) << 3;
8015
8016 // if d == 15 || m == 15 then UNPREDICTABLE;
8017 if ((d == 15) || (m == 15))
8018 return false;
8019
8020 break;
8021
8022 default:
8023 return false;
8024 }
8025
8026 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8027 if (!success)
8028 return false;
8029
8030 // rotated = ROR(R[m], rotation);
8031 uint64_t rotated = ROR (Rm, rotation, &success);
8032 if (!success)
8033 return false;
8034
8035 // R[d] = ZeroExtend(rotated<7:0>, 32);
8036 RegisterInfo source_reg;
8037 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
8038
8039 EmulateInstruction::Context context;
8040 context.type = eContextRegisterLoad;
8041 context.SetRegister (source_reg);
8042
8043 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
8044 return false;
8045 }
8046 return true;
8047 }
8048
8049 // UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
8050 // register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
8051 bool
EmulateUXTH(const uint32_t opcode,const ARMEncoding encoding)8052 EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding)
8053 {
8054 #if 0
8055 if ConditionPassed() then
8056 EncodingSpecificOperations();
8057 rotated = ROR(R[m], rotation);
8058 R[d] = ZeroExtend(rotated<15:0>, 32);
8059 #endif
8060
8061 bool success = false;
8062
8063 if (ConditionPassed(opcode))
8064 {
8065 uint32_t d;
8066 uint32_t m;
8067 uint32_t rotation;
8068
8069 switch (encoding)
8070 {
8071 case eEncodingT1:
8072 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8073 d = Bits32 (opcode, 2, 0);
8074 m = Bits32 (opcode, 5, 3);
8075 rotation = 0;
8076
8077 break;
8078
8079 case eEncodingT2:
8080 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8081 d = Bits32 (opcode, 11, 8);
8082 m = Bits32 (opcode, 3, 0);
8083 rotation = Bits32 (opcode, 5, 4) << 3;
8084
8085 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8086 if (BadReg (d) || BadReg (m))
8087 return false;
8088
8089 break;
8090
8091 case eEncodingA1:
8092 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8093 d = Bits32 (opcode, 15, 12);
8094 m = Bits32 (opcode, 3, 0);
8095 rotation = Bits32 (opcode, 11, 10) << 3;
8096
8097 // if d == 15 || m == 15 then UNPREDICTABLE;
8098 if ((d == 15) || (m == 15))
8099 return false;
8100
8101 break;
8102
8103 default:
8104 return false;
8105 }
8106
8107 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8108 if (!success)
8109 return false;
8110
8111 // rotated = ROR(R[m], rotation);
8112 uint64_t rotated = ROR (Rm, rotation, &success);
8113 if (!success)
8114 return false;
8115
8116 // R[d] = ZeroExtend(rotated<15:0>, 32);
8117 RegisterInfo source_reg;
8118 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
8119
8120 EmulateInstruction::Context context;
8121 context.type = eContextRegisterLoad;
8122 context.SetRegister (source_reg);
8123
8124 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
8125 return false;
8126 }
8127 return true;
8128 }
8129
8130 // RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
8131 // word respectively.
8132 bool
EmulateRFE(const uint32_t opcode,const ARMEncoding encoding)8133 EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding)
8134 {
8135 #if 0
8136 if ConditionPassed() then
8137 EncodingSpecificOperations();
8138 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8139 UNPREDICTABLE;
8140 else
8141 address = if increment then R[n] else R[n]-8;
8142 if wordhigher then address = address+4;
8143 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
8144 BranchWritePC(MemA[address,4]);
8145 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8146 #endif
8147
8148 bool success = false;
8149
8150 if (ConditionPassed(opcode))
8151 {
8152 uint32_t n;
8153 bool wback;
8154 bool increment;
8155 bool wordhigher;
8156
8157 // EncodingSpecificOperations();
8158 switch (encoding)
8159 {
8160 case eEncodingT1:
8161 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE;
8162 n = Bits32 (opcode, 19, 16);
8163 wback = BitIsSet (opcode, 21);
8164 increment = false;
8165 wordhigher = false;
8166
8167 // if n == 15 then UNPREDICTABLE;
8168 if (n == 15)
8169 return false;
8170
8171 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8172 if (InITBlock() && !LastInITBlock())
8173 return false;
8174
8175 break;
8176
8177 case eEncodingT2:
8178 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
8179 n = Bits32 (opcode, 19, 16);
8180 wback = BitIsSet (opcode, 21);
8181 increment = true;
8182 wordhigher = false;
8183
8184 // if n == 15 then UNPREDICTABLE;
8185 if (n == 15)
8186 return false;
8187
8188 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8189 if (InITBlock() && !LastInITBlock())
8190 return false;
8191
8192 break;
8193
8194 case eEncodingA1:
8195 // n = UInt(Rn);
8196 n = Bits32 (opcode, 19, 16);
8197
8198 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
8199 wback = BitIsSet (opcode, 21);
8200 increment = BitIsSet (opcode, 23);
8201 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
8202
8203 // if n == 15 then UNPREDICTABLE;
8204 if (n == 15)
8205 return false;
8206
8207 break;
8208
8209 default:
8210 return false;
8211 }
8212
8213 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8214 if (!CurrentModeIsPrivileged ())
8215 // UNPREDICTABLE;
8216 return false;
8217 else
8218 {
8219 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8220 if (!success)
8221 return false;
8222
8223 addr_t address;
8224 // address = if increment then R[n] else R[n]-8;
8225 if (increment)
8226 address = Rn;
8227 else
8228 address = Rn - 8;
8229
8230 // if wordhigher then address = address+4;
8231 if (wordhigher)
8232 address = address + 4;
8233
8234 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
8235 RegisterInfo base_reg;
8236 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
8237
8238 EmulateInstruction::Context context;
8239 context.type = eContextReturnFromException;
8240 context.SetRegisterPlusOffset (base_reg, address - Rn);
8241
8242 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
8243 if (!success)
8244 return false;
8245
8246 CPSRWriteByInstr (data, 15, true);
8247
8248 // BranchWritePC(MemA[address,4]);
8249 uint64_t data2 = MemARead (context, address, 4, 0, &success);
8250 if (!success)
8251 return false;
8252
8253 BranchWritePC (context, data2);
8254
8255 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8256 if (wback)
8257 {
8258 context.type = eContextAdjustBaseRegister;
8259 if (increment)
8260 {
8261 context.SetOffset (8);
8262 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
8263 return false;
8264 }
8265 else
8266 {
8267 context.SetOffset (-8);
8268 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
8269 return false;
8270 }
8271 } // if wback
8272 }
8273 } // if ConditionPassed()
8274 return true;
8275 }
8276
8277 // Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
8278 // and writes the result to the destination register. It can optionally update the condition flags based on
8279 // the result.
8280 bool
EmulateEORImm(const uint32_t opcode,const ARMEncoding encoding)8281 EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding)
8282 {
8283 #if 0
8284 // ARM pseudo code...
8285 if ConditionPassed() then
8286 EncodingSpecificOperations();
8287 result = R[n] EOR imm32;
8288 if d == 15 then // Can only occur for ARM encoding
8289 ALUWritePC(result); // setflags is always FALSE here
8290 else
8291 R[d] = result;
8292 if setflags then
8293 APSR.N = result<31>;
8294 APSR.Z = IsZeroBit(result);
8295 APSR.C = carry;
8296 // APSR.V unchanged
8297 #endif
8298
8299 bool success = false;
8300
8301 if (ConditionPassed(opcode))
8302 {
8303 uint32_t Rd, Rn;
8304 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8305 bool setflags;
8306 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8307 switch (encoding)
8308 {
8309 case eEncodingT1:
8310 Rd = Bits32(opcode, 11, 8);
8311 Rn = Bits32(opcode, 19, 16);
8312 setflags = BitIsSet(opcode, 20);
8313 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8314 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8315 if (Rd == 15 && setflags)
8316 return EmulateTEQImm (opcode, eEncodingT1);
8317 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8318 return false;
8319 break;
8320 case eEncodingA1:
8321 Rd = Bits32(opcode, 15, 12);
8322 Rn = Bits32(opcode, 19, 16);
8323 setflags = BitIsSet(opcode, 20);
8324 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8325
8326 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8327 if (Rd == 15 && setflags)
8328 return EmulateSUBSPcLrEtc (opcode, encoding);
8329 break;
8330 default:
8331 return false;
8332 }
8333
8334 // Read the first operand.
8335 uint32_t val1 = ReadCoreReg(Rn, &success);
8336 if (!success)
8337 return false;
8338
8339 uint32_t result = val1 ^ imm32;
8340
8341 EmulateInstruction::Context context;
8342 context.type = EmulateInstruction::eContextImmediate;
8343 context.SetNoArgs ();
8344
8345 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8346 return false;
8347 }
8348 return true;
8349 }
8350
8351 // Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
8352 // optionally-shifted register value, and writes the result to the destination register.
8353 // It can optionally update the condition flags based on the result.
8354 bool
EmulateEORReg(const uint32_t opcode,const ARMEncoding encoding)8355 EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding)
8356 {
8357 #if 0
8358 // ARM pseudo code...
8359 if ConditionPassed() then
8360 EncodingSpecificOperations();
8361 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8362 result = R[n] EOR shifted;
8363 if d == 15 then // Can only occur for ARM encoding
8364 ALUWritePC(result); // setflags is always FALSE here
8365 else
8366 R[d] = result;
8367 if setflags then
8368 APSR.N = result<31>;
8369 APSR.Z = IsZeroBit(result);
8370 APSR.C = carry;
8371 // APSR.V unchanged
8372 #endif
8373
8374 bool success = false;
8375
8376 if (ConditionPassed(opcode))
8377 {
8378 uint32_t Rd, Rn, Rm;
8379 ARM_ShifterType shift_t;
8380 uint32_t shift_n; // the shift applied to the value read from Rm
8381 bool setflags;
8382 uint32_t carry;
8383 switch (encoding)
8384 {
8385 case eEncodingT1:
8386 Rd = Rn = Bits32(opcode, 2, 0);
8387 Rm = Bits32(opcode, 5, 3);
8388 setflags = !InITBlock();
8389 shift_t = SRType_LSL;
8390 shift_n = 0;
8391 break;
8392 case eEncodingT2:
8393 Rd = Bits32(opcode, 11, 8);
8394 Rn = Bits32(opcode, 19, 16);
8395 Rm = Bits32(opcode, 3, 0);
8396 setflags = BitIsSet(opcode, 20);
8397 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8398 // if Rd == '1111' && S == '1' then SEE TEQ (register);
8399 if (Rd == 15 && setflags)
8400 return EmulateTEQReg (opcode, eEncodingT1);
8401 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8402 return false;
8403 break;
8404 case eEncodingA1:
8405 Rd = Bits32(opcode, 15, 12);
8406 Rn = Bits32(opcode, 19, 16);
8407 Rm = Bits32(opcode, 3, 0);
8408 setflags = BitIsSet(opcode, 20);
8409 shift_n = DecodeImmShiftARM(opcode, shift_t);
8410
8411 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8412 if (Rd == 15 && setflags)
8413 return EmulateSUBSPcLrEtc (opcode, encoding);
8414 break;
8415 default:
8416 return false;
8417 }
8418
8419 // Read the first operand.
8420 uint32_t val1 = ReadCoreReg(Rn, &success);
8421 if (!success)
8422 return false;
8423
8424 // Read the second operand.
8425 uint32_t val2 = ReadCoreReg(Rm, &success);
8426 if (!success)
8427 return false;
8428
8429 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
8430 if (!success)
8431 return false;
8432 uint32_t result = val1 ^ shifted;
8433
8434 EmulateInstruction::Context context;
8435 context.type = EmulateInstruction::eContextImmediate;
8436 context.SetNoArgs ();
8437
8438 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8439 return false;
8440 }
8441 return true;
8442 }
8443
8444 // Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8445 // writes the result to the destination register. It can optionally update the condition flags based
8446 // on the result.
8447 bool
EmulateORRImm(const uint32_t opcode,const ARMEncoding encoding)8448 EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding)
8449 {
8450 #if 0
8451 // ARM pseudo code...
8452 if ConditionPassed() then
8453 EncodingSpecificOperations();
8454 result = R[n] OR imm32;
8455 if d == 15 then // Can only occur for ARM encoding
8456 ALUWritePC(result); // setflags is always FALSE here
8457 else
8458 R[d] = result;
8459 if setflags then
8460 APSR.N = result<31>;
8461 APSR.Z = IsZeroBit(result);
8462 APSR.C = carry;
8463 // APSR.V unchanged
8464 #endif
8465
8466 bool success = false;
8467
8468 if (ConditionPassed(opcode))
8469 {
8470 uint32_t Rd, Rn;
8471 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8472 bool setflags;
8473 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8474 switch (encoding)
8475 {
8476 case eEncodingT1:
8477 Rd = Bits32(opcode, 11, 8);
8478 Rn = Bits32(opcode, 19, 16);
8479 setflags = BitIsSet(opcode, 20);
8480 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8481 // if Rn == '1111' then SEE MOV (immediate);
8482 if (Rn == 15)
8483 return EmulateMOVRdImm (opcode, eEncodingT2);
8484 if (BadReg(Rd) || Rn == 13)
8485 return false;
8486 break;
8487 case eEncodingA1:
8488 Rd = Bits32(opcode, 15, 12);
8489 Rn = Bits32(opcode, 19, 16);
8490 setflags = BitIsSet(opcode, 20);
8491 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8492
8493 if (Rd == 15 && setflags)
8494 return EmulateSUBSPcLrEtc (opcode, encoding);
8495 break;
8496 default:
8497 return false;
8498 }
8499
8500 // Read the first operand.
8501 uint32_t val1 = ReadCoreReg(Rn, &success);
8502 if (!success)
8503 return false;
8504
8505 uint32_t result = val1 | imm32;
8506
8507 EmulateInstruction::Context context;
8508 context.type = EmulateInstruction::eContextImmediate;
8509 context.SetNoArgs ();
8510
8511 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8512 return false;
8513 }
8514 return true;
8515 }
8516
8517 // Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8518 // value, and writes the result to the destination register. It can optionally update the condition flags based
8519 // on the result.
8520 bool
EmulateORRReg(const uint32_t opcode,const ARMEncoding encoding)8521 EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding)
8522 {
8523 #if 0
8524 // ARM pseudo code...
8525 if ConditionPassed() then
8526 EncodingSpecificOperations();
8527 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8528 result = R[n] OR shifted;
8529 if d == 15 then // Can only occur for ARM encoding
8530 ALUWritePC(result); // setflags is always FALSE here
8531 else
8532 R[d] = result;
8533 if setflags then
8534 APSR.N = result<31>;
8535 APSR.Z = IsZeroBit(result);
8536 APSR.C = carry;
8537 // APSR.V unchanged
8538 #endif
8539
8540 bool success = false;
8541
8542 if (ConditionPassed(opcode))
8543 {
8544 uint32_t Rd, Rn, Rm;
8545 ARM_ShifterType shift_t;
8546 uint32_t shift_n; // the shift applied to the value read from Rm
8547 bool setflags;
8548 uint32_t carry;
8549 switch (encoding)
8550 {
8551 case eEncodingT1:
8552 Rd = Rn = Bits32(opcode, 2, 0);
8553 Rm = Bits32(opcode, 5, 3);
8554 setflags = !InITBlock();
8555 shift_t = SRType_LSL;
8556 shift_n = 0;
8557 break;
8558 case eEncodingT2:
8559 Rd = Bits32(opcode, 11, 8);
8560 Rn = Bits32(opcode, 19, 16);
8561 Rm = Bits32(opcode, 3, 0);
8562 setflags = BitIsSet(opcode, 20);
8563 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8564 // if Rn == '1111' then SEE MOV (register);
8565 if (Rn == 15)
8566 return EmulateMOVRdRm (opcode, eEncodingT3);
8567 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8568 return false;
8569 break;
8570 case eEncodingA1:
8571 Rd = Bits32(opcode, 15, 12);
8572 Rn = Bits32(opcode, 19, 16);
8573 Rm = Bits32(opcode, 3, 0);
8574 setflags = BitIsSet(opcode, 20);
8575 shift_n = DecodeImmShiftARM(opcode, shift_t);
8576
8577 if (Rd == 15 && setflags)
8578 return EmulateSUBSPcLrEtc (opcode, encoding);
8579 break;
8580 default:
8581 return false;
8582 }
8583
8584 // Read the first operand.
8585 uint32_t val1 = ReadCoreReg(Rn, &success);
8586 if (!success)
8587 return false;
8588
8589 // Read the second operand.
8590 uint32_t val2 = ReadCoreReg(Rm, &success);
8591 if (!success)
8592 return false;
8593
8594 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
8595 if (!success)
8596 return false;
8597 uint32_t result = val1 | shifted;
8598
8599 EmulateInstruction::Context context;
8600 context.type = EmulateInstruction::eContextImmediate;
8601 context.SetNoArgs ();
8602
8603 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8604 return false;
8605 }
8606 return true;
8607 }
8608
8609 // Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8610 // the destination register. It can optionally update the condition flags based on the result.
8611 bool
EmulateRSBImm(const uint32_t opcode,const ARMEncoding encoding)8612 EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding)
8613 {
8614 #if 0
8615 // ARM pseudo code...
8616 if ConditionPassed() then
8617 EncodingSpecificOperations();
8618 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8619 if d == 15 then // Can only occur for ARM encoding
8620 ALUWritePC(result); // setflags is always FALSE here
8621 else
8622 R[d] = result;
8623 if setflags then
8624 APSR.N = result<31>;
8625 APSR.Z = IsZeroBit(result);
8626 APSR.C = carry;
8627 APSR.V = overflow;
8628 #endif
8629
8630 bool success = false;
8631
8632 uint32_t Rd; // the destination register
8633 uint32_t Rn; // the first operand
8634 bool setflags;
8635 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8636 switch (encoding) {
8637 case eEncodingT1:
8638 Rd = Bits32(opcode, 2, 0);
8639 Rn = Bits32(opcode, 5, 3);
8640 setflags = !InITBlock();
8641 imm32 = 0;
8642 break;
8643 case eEncodingT2:
8644 Rd = Bits32(opcode, 11, 8);
8645 Rn = Bits32(opcode, 19, 16);
8646 setflags = BitIsSet(opcode, 20);
8647 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8648 if (BadReg(Rd) || BadReg(Rn))
8649 return false;
8650 break;
8651 case eEncodingA1:
8652 Rd = Bits32(opcode, 15, 12);
8653 Rn = Bits32(opcode, 19, 16);
8654 setflags = BitIsSet(opcode, 20);
8655 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8656
8657 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8658 if (Rd == 15 && setflags)
8659 return EmulateSUBSPcLrEtc (opcode, encoding);
8660 break;
8661 default:
8662 return false;
8663 }
8664 // Read the register value from the operand register Rn.
8665 uint32_t reg_val = ReadCoreReg(Rn, &success);
8666 if (!success)
8667 return false;
8668
8669 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8670
8671 EmulateInstruction::Context context;
8672 context.type = EmulateInstruction::eContextImmediate;
8673 context.SetNoArgs ();
8674
8675 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8676 return false;
8677
8678 return true;
8679 }
8680
8681 // Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8682 // result to the destination register. It can optionally update the condition flags based on the result.
8683 bool
EmulateRSBReg(const uint32_t opcode,const ARMEncoding encoding)8684 EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding)
8685 {
8686 #if 0
8687 // ARM pseudo code...
8688 if ConditionPassed() then
8689 EncodingSpecificOperations();
8690 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8691 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8692 if d == 15 then // Can only occur for ARM encoding
8693 ALUWritePC(result); // setflags is always FALSE here
8694 else
8695 R[d] = result;
8696 if setflags then
8697 APSR.N = result<31>;
8698 APSR.Z = IsZeroBit(result);
8699 APSR.C = carry;
8700 APSR.V = overflow;
8701 #endif
8702
8703 bool success = false;
8704
8705 uint32_t Rd; // the destination register
8706 uint32_t Rn; // the first operand
8707 uint32_t Rm; // the second operand
8708 bool setflags;
8709 ARM_ShifterType shift_t;
8710 uint32_t shift_n; // the shift applied to the value read from Rm
8711 switch (encoding) {
8712 case eEncodingT1:
8713 Rd = Bits32(opcode, 11, 8);
8714 Rn = Bits32(opcode, 19, 16);
8715 Rm = Bits32(opcode, 3, 0);
8716 setflags = BitIsSet(opcode, 20);
8717 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8718 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8719 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8720 return false;
8721 break;
8722 case eEncodingA1:
8723 Rd = Bits32(opcode, 15, 12);
8724 Rn = Bits32(opcode, 19, 16);
8725 Rm = Bits32(opcode, 3, 0);
8726 setflags = BitIsSet(opcode, 20);
8727 shift_n = DecodeImmShiftARM(opcode, shift_t);
8728
8729 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8730 if (Rd == 15 && setflags)
8731 return EmulateSUBSPcLrEtc (opcode, encoding);
8732 break;
8733 default:
8734 return false;
8735 }
8736 // Read the register value from register Rn.
8737 uint32_t val1 = ReadCoreReg(Rn, &success);
8738 if (!success)
8739 return false;
8740
8741 // Read the register value from register Rm.
8742 uint32_t val2 = ReadCoreReg(Rm, &success);
8743 if (!success)
8744 return false;
8745
8746 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
8747 if (!success)
8748 return false;
8749 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8750
8751 EmulateInstruction::Context context;
8752 context.type = EmulateInstruction::eContextImmediate;
8753 context.SetNoArgs();
8754 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8755 return false;
8756
8757 return true;
8758 }
8759
8760 // Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8761 // an immediate value, and writes the result to the destination register. It can optionally update the condition
8762 // flags based on the result.
8763 bool
EmulateRSCImm(const uint32_t opcode,const ARMEncoding encoding)8764 EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding)
8765 {
8766 #if 0
8767 // ARM pseudo code...
8768 if ConditionPassed() then
8769 EncodingSpecificOperations();
8770 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8771 if d == 15 then
8772 ALUWritePC(result); // setflags is always FALSE here
8773 else
8774 R[d] = result;
8775 if setflags then
8776 APSR.N = result<31>;
8777 APSR.Z = IsZeroBit(result);
8778 APSR.C = carry;
8779 APSR.V = overflow;
8780 #endif
8781
8782 bool success = false;
8783
8784 uint32_t Rd; // the destination register
8785 uint32_t Rn; // the first operand
8786 bool setflags;
8787 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8788 switch (encoding) {
8789 case eEncodingA1:
8790 Rd = Bits32(opcode, 15, 12);
8791 Rn = Bits32(opcode, 19, 16);
8792 setflags = BitIsSet(opcode, 20);
8793 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8794
8795 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8796 if (Rd == 15 && setflags)
8797 return EmulateSUBSPcLrEtc (opcode, encoding);
8798 break;
8799 default:
8800 return false;
8801 }
8802 // Read the register value from the operand register Rn.
8803 uint32_t reg_val = ReadCoreReg(Rn, &success);
8804 if (!success)
8805 return false;
8806
8807 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8808
8809 EmulateInstruction::Context context;
8810 context.type = EmulateInstruction::eContextImmediate;
8811 context.SetNoArgs ();
8812
8813 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8814 return false;
8815
8816 return true;
8817 }
8818
8819 // Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8820 // optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8821 // condition flags based on the result.
8822 bool
EmulateRSCReg(const uint32_t opcode,const ARMEncoding encoding)8823 EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding)
8824 {
8825 #if 0
8826 // ARM pseudo code...
8827 if ConditionPassed() then
8828 EncodingSpecificOperations();
8829 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8830 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8831 if d == 15 then
8832 ALUWritePC(result); // setflags is always FALSE here
8833 else
8834 R[d] = result;
8835 if setflags then
8836 APSR.N = result<31>;
8837 APSR.Z = IsZeroBit(result);
8838 APSR.C = carry;
8839 APSR.V = overflow;
8840 #endif
8841
8842 bool success = false;
8843
8844 uint32_t Rd; // the destination register
8845 uint32_t Rn; // the first operand
8846 uint32_t Rm; // the second operand
8847 bool setflags;
8848 ARM_ShifterType shift_t;
8849 uint32_t shift_n; // the shift applied to the value read from Rm
8850 switch (encoding) {
8851 case eEncodingA1:
8852 Rd = Bits32(opcode, 15, 12);
8853 Rn = Bits32(opcode, 19, 16);
8854 Rm = Bits32(opcode, 3, 0);
8855 setflags = BitIsSet(opcode, 20);
8856 shift_n = DecodeImmShiftARM(opcode, shift_t);
8857
8858 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8859 if (Rd == 15 && setflags)
8860 return EmulateSUBSPcLrEtc (opcode, encoding);
8861 break;
8862 default:
8863 return false;
8864 }
8865 // Read the register value from register Rn.
8866 uint32_t val1 = ReadCoreReg(Rn, &success);
8867 if (!success)
8868 return false;
8869
8870 // Read the register value from register Rm.
8871 uint32_t val2 = ReadCoreReg(Rm, &success);
8872 if (!success)
8873 return false;
8874
8875 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
8876 if (!success)
8877 return false;
8878 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8879
8880 EmulateInstruction::Context context;
8881 context.type = EmulateInstruction::eContextImmediate;
8882 context.SetNoArgs();
8883 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8884 return false;
8885
8886 return true;
8887 }
8888
8889 // Subtract with Carry (immediate) subtracts an immediate value and the value of
8890 // NOT (Carry flag) from a register value, and writes the result to the destination register.
8891 // It can optionally update the condition flags based on the result.
8892 bool
EmulateSBCImm(const uint32_t opcode,const ARMEncoding encoding)8893 EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding)
8894 {
8895 #if 0
8896 // ARM pseudo code...
8897 if ConditionPassed() then
8898 EncodingSpecificOperations();
8899 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
8900 if d == 15 then // Can only occur for ARM encoding
8901 ALUWritePC(result); // setflags is always FALSE here
8902 else
8903 R[d] = result;
8904 if setflags then
8905 APSR.N = result<31>;
8906 APSR.Z = IsZeroBit(result);
8907 APSR.C = carry;
8908 APSR.V = overflow;
8909 #endif
8910
8911 bool success = false;
8912
8913 uint32_t Rd; // the destination register
8914 uint32_t Rn; // the first operand
8915 bool setflags;
8916 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8917 switch (encoding) {
8918 case eEncodingT1:
8919 Rd = Bits32(opcode, 11, 8);
8920 Rn = Bits32(opcode, 19, 16);
8921 setflags = BitIsSet(opcode, 20);
8922 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8923 if (BadReg(Rd) || BadReg(Rn))
8924 return false;
8925 break;
8926 case eEncodingA1:
8927 Rd = Bits32(opcode, 15, 12);
8928 Rn = Bits32(opcode, 19, 16);
8929 setflags = BitIsSet(opcode, 20);
8930 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8931
8932 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8933 if (Rd == 15 && setflags)
8934 return EmulateSUBSPcLrEtc (opcode, encoding);
8935 break;
8936 default:
8937 return false;
8938 }
8939 // Read the register value from the operand register Rn.
8940 uint32_t reg_val = ReadCoreReg(Rn, &success);
8941 if (!success)
8942 return false;
8943
8944 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8945
8946 EmulateInstruction::Context context;
8947 context.type = EmulateInstruction::eContextImmediate;
8948 context.SetNoArgs ();
8949
8950 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8951 return false;
8952
8953 return true;
8954 }
8955
8956 // Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8957 // NOT (Carry flag) from a register value, and writes the result to the destination register.
8958 // It can optionally update the condition flags based on the result.
8959 bool
EmulateSBCReg(const uint32_t opcode,const ARMEncoding encoding)8960 EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding)
8961 {
8962 #if 0
8963 // ARM pseudo code...
8964 if ConditionPassed() then
8965 EncodingSpecificOperations();
8966 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8967 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8968 if d == 15 then // Can only occur for ARM encoding
8969 ALUWritePC(result); // setflags is always FALSE here
8970 else
8971 R[d] = result;
8972 if setflags then
8973 APSR.N = result<31>;
8974 APSR.Z = IsZeroBit(result);
8975 APSR.C = carry;
8976 APSR.V = overflow;
8977 #endif
8978
8979 bool success = false;
8980
8981 uint32_t Rd; // the destination register
8982 uint32_t Rn; // the first operand
8983 uint32_t Rm; // the second operand
8984 bool setflags;
8985 ARM_ShifterType shift_t;
8986 uint32_t shift_n; // the shift applied to the value read from Rm
8987 switch (encoding) {
8988 case eEncodingT1:
8989 Rd = Rn = Bits32(opcode, 2, 0);
8990 Rm = Bits32(opcode, 5, 3);
8991 setflags = !InITBlock();
8992 shift_t = SRType_LSL;
8993 shift_n = 0;
8994 break;
8995 case eEncodingT2:
8996 Rd = Bits32(opcode, 11, 8);
8997 Rn = Bits32(opcode, 19, 16);
8998 Rm = Bits32(opcode, 3, 0);
8999 setflags = BitIsSet(opcode, 20);
9000 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9001 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
9002 return false;
9003 break;
9004 case eEncodingA1:
9005 Rd = Bits32(opcode, 15, 12);
9006 Rn = Bits32(opcode, 19, 16);
9007 Rm = Bits32(opcode, 3, 0);
9008 setflags = BitIsSet(opcode, 20);
9009 shift_n = DecodeImmShiftARM(opcode, shift_t);
9010
9011 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
9012 if (Rd == 15 && setflags)
9013 return EmulateSUBSPcLrEtc (opcode, encoding);
9014 break;
9015 default:
9016 return false;
9017 }
9018 // Read the register value from register Rn.
9019 uint32_t val1 = ReadCoreReg(Rn, &success);
9020 if (!success)
9021 return false;
9022
9023 // Read the register value from register Rm.
9024 uint32_t val2 = ReadCoreReg(Rm, &success);
9025 if (!success)
9026 return false;
9027
9028 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
9029 if (!success)
9030 return false;
9031 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
9032
9033 EmulateInstruction::Context context;
9034 context.type = EmulateInstruction::eContextImmediate;
9035 context.SetNoArgs();
9036 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9037 return false;
9038
9039 return true;
9040 }
9041
9042 // This instruction subtracts an immediate value from a register value, and writes the result
9043 // to the destination register. It can optionally update the condition flags based on the result.
9044 bool
EmulateSUBImmThumb(const uint32_t opcode,const ARMEncoding encoding)9045 EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding)
9046 {
9047 #if 0
9048 // ARM pseudo code...
9049 if ConditionPassed() then
9050 EncodingSpecificOperations();
9051 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9052 R[d] = result;
9053 if setflags then
9054 APSR.N = result<31>;
9055 APSR.Z = IsZeroBit(result);
9056 APSR.C = carry;
9057 APSR.V = overflow;
9058 #endif
9059
9060 bool success = false;
9061
9062 uint32_t Rd; // the destination register
9063 uint32_t Rn; // the first operand
9064 bool setflags;
9065 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
9066 switch (encoding) {
9067 case eEncodingT1:
9068 Rd = Bits32(opcode, 2, 0);
9069 Rn = Bits32(opcode, 5, 3);
9070 setflags = !InITBlock();
9071 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
9072 break;
9073 case eEncodingT2:
9074 Rd = Rn = Bits32(opcode, 10, 8);
9075 setflags = !InITBlock();
9076 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
9077 break;
9078 case eEncodingT3:
9079 Rd = Bits32(opcode, 11, 8);
9080 Rn = Bits32(opcode, 19, 16);
9081 setflags = BitIsSet(opcode, 20);
9082 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9083
9084 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
9085 if (Rd == 15 && setflags)
9086 return EmulateCMPImm (opcode, eEncodingT2);
9087
9088 // if Rn == '1101' then SEE SUB (SP minus immediate);
9089 if (Rn == 13)
9090 return EmulateSUBSPImm (opcode, eEncodingT2);
9091
9092 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
9093 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
9094 return false;
9095 break;
9096 case eEncodingT4:
9097 Rd = Bits32(opcode, 11, 8);
9098 Rn = Bits32(opcode, 19, 16);
9099 setflags = BitIsSet(opcode, 20);
9100 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
9101
9102 // if Rn == '1111' then SEE ADR;
9103 if (Rn == 15)
9104 return EmulateADR (opcode, eEncodingT2);
9105
9106 // if Rn == '1101' then SEE SUB (SP minus immediate);
9107 if (Rn == 13)
9108 return EmulateSUBSPImm (opcode, eEncodingT3);
9109
9110 if (BadReg(Rd))
9111 return false;
9112 break;
9113 default:
9114 return false;
9115 }
9116 // Read the register value from the operand register Rn.
9117 uint32_t reg_val = ReadCoreReg(Rn, &success);
9118 if (!success)
9119 return false;
9120
9121 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9122
9123 EmulateInstruction::Context context;
9124 context.type = EmulateInstruction::eContextImmediate;
9125 context.SetNoArgs ();
9126
9127 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9128 return false;
9129
9130 return true;
9131 }
9132
9133 // This instruction subtracts an immediate value from a register value, and writes the result
9134 // to the destination register. It can optionally update the condition flags based on the result.
9135 bool
EmulateSUBImmARM(const uint32_t opcode,const ARMEncoding encoding)9136 EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding)
9137 {
9138 #if 0
9139 // ARM pseudo code...
9140 if ConditionPassed() then
9141 EncodingSpecificOperations();
9142 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9143 if d == 15 then
9144 ALUWritePC(result); // setflags is always FALSE here
9145 else
9146 R[d] = result;
9147 if setflags then
9148 APSR.N = result<31>;
9149 APSR.Z = IsZeroBit(result);
9150 APSR.C = carry;
9151 APSR.V = overflow;
9152 #endif
9153
9154 bool success = false;
9155
9156 uint32_t Rd; // the destination register
9157 uint32_t Rn; // the first operand
9158 bool setflags;
9159 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
9160 switch (encoding) {
9161 case eEncodingA1:
9162 Rd = Bits32(opcode, 15, 12);
9163 Rn = Bits32(opcode, 19, 16);
9164 setflags = BitIsSet(opcode, 20);
9165 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9166
9167 // if Rn == '1111' && S == '0' then SEE ADR;
9168 if (Rn == 15 && !setflags)
9169 return EmulateADR (opcode, eEncodingA2);
9170
9171 // if Rn == '1101' then SEE SUB (SP minus immediate);
9172 if (Rn == 13)
9173 return EmulateSUBSPImm (opcode, eEncodingA1);
9174
9175 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
9176 if (Rd == 15 && setflags)
9177 return EmulateSUBSPcLrEtc (opcode, encoding);
9178 break;
9179 default:
9180 return false;
9181 }
9182 // Read the register value from the operand register Rn.
9183 uint32_t reg_val = ReadCoreReg(Rn, &success);
9184 if (!success)
9185 return false;
9186
9187 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9188
9189 EmulateInstruction::Context context;
9190 context.type = EmulateInstruction::eContextImmediate;
9191 context.SetNoArgs ();
9192
9193 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9194 return false;
9195
9196 return true;
9197 }
9198
9199 // Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
9200 // immediate value. It updates the condition flags based on the result, and discards the result.
9201 bool
EmulateTEQImm(const uint32_t opcode,const ARMEncoding encoding)9202 EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding)
9203 {
9204 #if 0
9205 // ARM pseudo code...
9206 if ConditionPassed() then
9207 EncodingSpecificOperations();
9208 result = R[n] EOR imm32;
9209 APSR.N = result<31>;
9210 APSR.Z = IsZeroBit(result);
9211 APSR.C = carry;
9212 // APSR.V unchanged
9213 #endif
9214
9215 bool success = false;
9216
9217 if (ConditionPassed(opcode))
9218 {
9219 uint32_t Rn;
9220 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9221 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9222 switch (encoding)
9223 {
9224 case eEncodingT1:
9225 Rn = Bits32(opcode, 19, 16);
9226 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9227 if (BadReg(Rn))
9228 return false;
9229 break;
9230 case eEncodingA1:
9231 Rn = Bits32(opcode, 19, 16);
9232 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9233 break;
9234 default:
9235 return false;
9236 }
9237
9238 // Read the first operand.
9239 uint32_t val1 = ReadCoreReg(Rn, &success);
9240 if (!success)
9241 return false;
9242
9243 uint32_t result = val1 ^ imm32;
9244
9245 EmulateInstruction::Context context;
9246 context.type = EmulateInstruction::eContextImmediate;
9247 context.SetNoArgs ();
9248
9249 if (!WriteFlags(context, result, carry))
9250 return false;
9251 }
9252 return true;
9253 }
9254
9255 // Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
9256 // optionally-shifted register value. It updates the condition flags based on the result, and discards
9257 // the result.
9258 bool
EmulateTEQReg(const uint32_t opcode,const ARMEncoding encoding)9259 EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding)
9260 {
9261 #if 0
9262 // ARM pseudo code...
9263 if ConditionPassed() then
9264 EncodingSpecificOperations();
9265 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9266 result = R[n] EOR shifted;
9267 APSR.N = result<31>;
9268 APSR.Z = IsZeroBit(result);
9269 APSR.C = carry;
9270 // APSR.V unchanged
9271 #endif
9272
9273 bool success = false;
9274
9275 if (ConditionPassed(opcode))
9276 {
9277 uint32_t Rn, Rm;
9278 ARM_ShifterType shift_t;
9279 uint32_t shift_n; // the shift applied to the value read from Rm
9280 uint32_t carry;
9281 switch (encoding)
9282 {
9283 case eEncodingT1:
9284 Rn = Bits32(opcode, 19, 16);
9285 Rm = Bits32(opcode, 3, 0);
9286 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9287 if (BadReg(Rn) || BadReg(Rm))
9288 return false;
9289 break;
9290 case eEncodingA1:
9291 Rn = Bits32(opcode, 19, 16);
9292 Rm = Bits32(opcode, 3, 0);
9293 shift_n = DecodeImmShiftARM(opcode, shift_t);
9294 break;
9295 default:
9296 return false;
9297 }
9298
9299 // Read the first operand.
9300 uint32_t val1 = ReadCoreReg(Rn, &success);
9301 if (!success)
9302 return false;
9303
9304 // Read the second operand.
9305 uint32_t val2 = ReadCoreReg(Rm, &success);
9306 if (!success)
9307 return false;
9308
9309 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9310 if (!success)
9311 return false;
9312 uint32_t result = val1 ^ shifted;
9313
9314 EmulateInstruction::Context context;
9315 context.type = EmulateInstruction::eContextImmediate;
9316 context.SetNoArgs ();
9317
9318 if (!WriteFlags(context, result, carry))
9319 return false;
9320 }
9321 return true;
9322 }
9323
9324 // Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
9325 // It updates the condition flags based on the result, and discards the result.
9326 bool
EmulateTSTImm(const uint32_t opcode,const ARMEncoding encoding)9327 EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding)
9328 {
9329 #if 0
9330 // ARM pseudo code...
9331 if ConditionPassed() then
9332 EncodingSpecificOperations();
9333 result = R[n] AND imm32;
9334 APSR.N = result<31>;
9335 APSR.Z = IsZeroBit(result);
9336 APSR.C = carry;
9337 // APSR.V unchanged
9338 #endif
9339
9340 bool success = false;
9341
9342 if (ConditionPassed(opcode))
9343 {
9344 uint32_t Rn;
9345 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9346 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9347 switch (encoding)
9348 {
9349 case eEncodingT1:
9350 Rn = Bits32(opcode, 19, 16);
9351 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9352 if (BadReg(Rn))
9353 return false;
9354 break;
9355 case eEncodingA1:
9356 Rn = Bits32(opcode, 19, 16);
9357 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9358 break;
9359 default:
9360 return false;
9361 }
9362
9363 // Read the first operand.
9364 uint32_t val1 = ReadCoreReg(Rn, &success);
9365 if (!success)
9366 return false;
9367
9368 uint32_t result = val1 & imm32;
9369
9370 EmulateInstruction::Context context;
9371 context.type = EmulateInstruction::eContextImmediate;
9372 context.SetNoArgs ();
9373
9374 if (!WriteFlags(context, result, carry))
9375 return false;
9376 }
9377 return true;
9378 }
9379
9380 // Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9381 // It updates the condition flags based on the result, and discards the result.
9382 bool
EmulateTSTReg(const uint32_t opcode,const ARMEncoding encoding)9383 EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding)
9384 {
9385 #if 0
9386 // ARM pseudo code...
9387 if ConditionPassed() then
9388 EncodingSpecificOperations();
9389 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9390 result = R[n] AND shifted;
9391 APSR.N = result<31>;
9392 APSR.Z = IsZeroBit(result);
9393 APSR.C = carry;
9394 // APSR.V unchanged
9395 #endif
9396
9397 bool success = false;
9398
9399 if (ConditionPassed(opcode))
9400 {
9401 uint32_t Rn, Rm;
9402 ARM_ShifterType shift_t;
9403 uint32_t shift_n; // the shift applied to the value read from Rm
9404 uint32_t carry;
9405 switch (encoding)
9406 {
9407 case eEncodingT1:
9408 Rn = Bits32(opcode, 2, 0);
9409 Rm = Bits32(opcode, 5, 3);
9410 shift_t = SRType_LSL;
9411 shift_n = 0;
9412 break;
9413 case eEncodingT2:
9414 Rn = Bits32(opcode, 19, 16);
9415 Rm = Bits32(opcode, 3, 0);
9416 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9417 if (BadReg(Rn) || BadReg(Rm))
9418 return false;
9419 break;
9420 case eEncodingA1:
9421 Rn = Bits32(opcode, 19, 16);
9422 Rm = Bits32(opcode, 3, 0);
9423 shift_n = DecodeImmShiftARM(opcode, shift_t);
9424 break;
9425 default:
9426 return false;
9427 }
9428
9429 // Read the first operand.
9430 uint32_t val1 = ReadCoreReg(Rn, &success);
9431 if (!success)
9432 return false;
9433
9434 // Read the second operand.
9435 uint32_t val2 = ReadCoreReg(Rm, &success);
9436 if (!success)
9437 return false;
9438
9439 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9440 if (!success)
9441 return false;
9442 uint32_t result = val1 & shifted;
9443
9444 EmulateInstruction::Context context;
9445 context.type = EmulateInstruction::eContextImmediate;
9446 context.SetNoArgs ();
9447
9448 if (!WriteFlags(context, result, carry))
9449 return false;
9450 }
9451 return true;
9452 }
9453
9454 // A8.6.216 SUB (SP minus register)
9455 bool
EmulateSUBSPReg(const uint32_t opcode,const ARMEncoding encoding)9456 EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding)
9457 {
9458 #if 0
9459 if ConditionPassed() then
9460 EncodingSpecificOperations();
9461 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9462 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), �1�);
9463 if d == 15 then // Can only occur for ARM encoding
9464 ALUWritePC(result); // setflags is always FALSE here
9465 else
9466 R[d] = result;
9467 if setflags then
9468 APSR.N = result<31>;
9469 APSR.Z = IsZeroBit(result);
9470 APSR.C = carry;
9471 APSR.V = overflow;
9472 #endif
9473
9474 bool success = false;
9475
9476 if (ConditionPassed(opcode))
9477 {
9478 uint32_t d;
9479 uint32_t m;
9480 bool setflags;
9481 ARM_ShifterType shift_t;
9482 uint32_t shift_n;
9483
9484 switch (encoding)
9485 {
9486 case eEncodingT1:
9487 // d = UInt(Rd); m = UInt(Rm); setflags = (S == �1�);
9488 d = Bits32 (opcode, 11, 8);
9489 m = Bits32 (opcode, 3, 0);
9490 setflags = BitIsSet (opcode, 20);
9491
9492 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9493 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9494
9495 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then UNPREDICTABLE;
9496 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
9497 return false;
9498
9499 // if d == 15 || BadReg(m) then UNPREDICTABLE;
9500 if ((d == 15) || BadReg (m))
9501 return false;
9502 break;
9503
9504 case eEncodingA1:
9505 // d = UInt(Rd); m = UInt(Rm); setflags = (S == �1�);
9506 d = Bits32 (opcode, 15, 12);
9507 m = Bits32 (opcode, 3, 0);
9508 setflags = BitIsSet (opcode, 20);
9509
9510 // if Rd == �1111� && S == �1� then SEE SUBS PC, LR and related instructions;
9511 if (d == 15 && setflags)
9512 EmulateSUBSPcLrEtc (opcode, encoding);
9513
9514 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9515 shift_n = DecodeImmShiftARM (opcode, shift_t);
9516 break;
9517
9518 default:
9519 return false;
9520 }
9521
9522 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9523 uint32_t Rm = ReadCoreReg (m, &success);
9524 if (!success)
9525 return false;
9526
9527 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success);
9528 if (!success)
9529 return false;
9530
9531 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), �1�);
9532 uint32_t sp_val = ReadCoreReg (SP_REG, &success);
9533 if (!success)
9534 return false;
9535
9536 AddWithCarryResult res = AddWithCarry (sp_val, ~shifted, 1);
9537
9538 EmulateInstruction::Context context;
9539 context.type = eContextArithmetic;
9540 RegisterInfo sp_reg;
9541 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
9542 RegisterInfo dwarf_reg;
9543 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, dwarf_reg);
9544 context.SetRegisterRegisterOperands (sp_reg, dwarf_reg);
9545
9546 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
9547 return false;
9548 }
9549 return true;
9550 }
9551
9552
9553 // A8.6.7 ADD (register-shifted register)
9554 bool
EmulateADDRegShift(const uint32_t opcode,const ARMEncoding encoding)9555 EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding)
9556 {
9557 #if 0
9558 if ConditionPassed() then
9559 EncodingSpecificOperations();
9560 shift_n = UInt(R[s]<7:0>);
9561 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9562 (result, carry, overflow) = AddWithCarry(R[n], shifted, �0�);
9563 R[d] = result;
9564 if setflags then
9565 APSR.N = result<31>;
9566 APSR.Z = IsZeroBit(result);
9567 APSR.C = carry;
9568 APSR.V = overflow;
9569 #endif
9570
9571 bool success = false;
9572
9573 if (ConditionPassed(opcode))
9574 {
9575 uint32_t d;
9576 uint32_t n;
9577 uint32_t m;
9578 uint32_t s;
9579 bool setflags;
9580 ARM_ShifterType shift_t;
9581
9582 switch (encoding)
9583 {
9584 case eEncodingA1:
9585 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
9586 d = Bits32 (opcode, 15, 12);
9587 n = Bits32 (opcode, 19, 16);
9588 m = Bits32 (opcode, 3, 0);
9589 s = Bits32 (opcode, 11, 8);
9590
9591 // setflags = (S == �1�); shift_t = DecodeRegShift(type);
9592 setflags = BitIsSet (opcode, 20);
9593 shift_t = DecodeRegShift (Bits32 (opcode, 6, 5));
9594
9595 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
9596 if ((d == 15) || (m == 15) || (m == 15) || (s == 15))
9597 return false;
9598 break;
9599
9600 default:
9601 return false;
9602 }
9603
9604 // shift_n = UInt(R[s]<7:0>);
9605 uint32_t Rs = ReadCoreReg (s, &success);
9606 if (!success)
9607 return false;
9608
9609 uint32_t shift_n = Bits32 (Rs, 7, 0);
9610
9611 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9612 uint32_t Rm = ReadCoreReg (m, &success);
9613 if (!success)
9614 return false;
9615
9616 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success);
9617 if (!success)
9618 return false;
9619
9620 // (result, carry, overflow) = AddWithCarry(R[n], shifted, �0�);
9621 uint32_t Rn = ReadCoreReg (n, &success);
9622 if (!success)
9623 return false;
9624
9625 AddWithCarryResult res = AddWithCarry (Rn, shifted, 0);
9626
9627 // R[d] = result;
9628 EmulateInstruction::Context context;
9629 context.type = eContextArithmetic;
9630 RegisterInfo reg_n;
9631 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
9632 RegisterInfo reg_m;
9633 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m);
9634
9635 context.SetRegisterRegisterOperands (reg_n, reg_m);
9636
9637 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, res.result))
9638 return false;
9639
9640 // if setflags then
9641 // APSR.N = result<31>;
9642 // APSR.Z = IsZeroBit(result);
9643 // APSR.C = carry;
9644 // APSR.V = overflow;
9645 if (setflags)
9646 return WriteFlags (context, res.result, res.carry_out, res.overflow);
9647 }
9648 return true;
9649 }
9650
9651 // A8.6.213 SUB (register)
9652 bool
EmulateSUBReg(const uint32_t opcode,const ARMEncoding encoding)9653 EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding)
9654 {
9655 #if 0
9656 if ConditionPassed() then
9657 EncodingSpecificOperations();
9658 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9659 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), �1�);
9660 if d == 15 then // Can only occur for ARM encoding
9661 ALUWritePC(result); // setflags is always FALSE here
9662 else
9663 R[d] = result;
9664 if setflags then
9665 APSR.N = result<31>;
9666 APSR.Z = IsZeroBit(result);
9667 APSR.C = carry;
9668 APSR.V = overflow;
9669 #endif
9670
9671 bool success = false;
9672
9673 if (ConditionPassed(opcode))
9674 {
9675 uint32_t d;
9676 uint32_t n;
9677 uint32_t m;
9678 bool setflags;
9679 ARM_ShifterType shift_t;
9680 uint32_t shift_n;
9681
9682 switch (encoding)
9683 {
9684 case eEncodingT1:
9685 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
9686 d = Bits32 (opcode, 2, 0);
9687 n = Bits32 (opcode, 5, 3);
9688 m = Bits32 (opcode, 8, 6);
9689 setflags = !InITBlock();
9690
9691 // (shift_t, shift_n) = (SRType_LSL, 0);
9692 shift_t = SRType_LSL;
9693 shift_n = 0;
9694
9695 break;
9696
9697 case eEncodingT2:
9698 // if Rd == �1111� && S == �1� then SEE CMP (register);
9699 // if Rn == �1101� then SEE SUB (SP minus register);
9700 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == �1�);
9701 d = Bits32 (opcode, 11, 8);
9702 n = Bits32 (opcode, 19, 16);
9703 m = Bits32 (opcode, 3, 0);
9704 setflags = BitIsSet (opcode, 20);
9705
9706 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9707 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9708
9709 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then UNPREDICTABLE;
9710 if ((d == 13) || ((d == 15) && BitIsClear (opcode, 20)) || (n == 15) || BadReg (m))
9711 return false;
9712
9713 break;
9714
9715 case eEncodingA1:
9716 // if Rn == �1101� then SEE SUB (SP minus register);
9717 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == �1�);
9718 d = Bits32 (opcode, 15, 12);
9719 n = Bits32 (opcode, 19, 16);
9720 m = Bits32 (opcode, 3, 0);
9721 setflags = BitIsSet (opcode, 20);
9722
9723 // if Rd == �1111� && S == �1� then SEE SUBS PC, LR and related instructions;
9724 if ((d == 15) && setflags)
9725 EmulateSUBSPcLrEtc (opcode, encoding);
9726
9727 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9728 shift_n = DecodeImmShiftARM (opcode, shift_t);
9729
9730 break;
9731
9732 default:
9733 return false;
9734 }
9735
9736 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9737 uint32_t Rm = ReadCoreReg (m, &success);
9738 if (!success)
9739 return false;
9740
9741 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success);
9742 if (!success)
9743 return false;
9744
9745 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), �1�);
9746 uint32_t Rn = ReadCoreReg (n, &success);
9747 if (!success)
9748 return false;
9749
9750 AddWithCarryResult res = AddWithCarry (Rn, ~shifted, 1);
9751
9752 // if d == 15 then // Can only occur for ARM encoding
9753 // ALUWritePC(result); // setflags is always FALSE here
9754 // else
9755 // R[d] = result;
9756 // if setflags then
9757 // APSR.N = result<31>;
9758 // APSR.Z = IsZeroBit(result);
9759 // APSR.C = carry;
9760 // APSR.V = overflow;
9761
9762 EmulateInstruction::Context context;
9763 context.type = eContextArithmetic;
9764 RegisterInfo reg_n;
9765 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
9766 RegisterInfo reg_m;
9767 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m);
9768 context.SetRegisterRegisterOperands (reg_n, reg_m);
9769
9770 if (!WriteCoreRegOptionalFlags (context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
9771 return false;
9772 }
9773 return true;
9774 }
9775
9776 // A8.6.202 STREX
9777 // Store Register Exclusive calculates an address from a base register value and an immediate offset, and stores a
9778 // word from a register to memory if the executing processor has exclusive access to the memory addressed.
9779 bool
EmulateSTREX(const uint32_t opcode,const ARMEncoding encoding)9780 EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding)
9781 {
9782 #if 0
9783 if ConditionPassed() then
9784 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9785 address = R[n] + imm32;
9786 if ExclusiveMonitorsPass(address,4) then
9787 MemA[address,4] = R[t];
9788 R[d] = 0;
9789 else
9790 R[d] = 1;
9791 #endif
9792
9793 bool success = false;
9794
9795 if (ConditionPassed(opcode))
9796 {
9797 uint32_t d;
9798 uint32_t t;
9799 uint32_t n;
9800 uint32_t imm32;
9801 const uint32_t addr_byte_size = GetAddressByteSize();
9802
9803 switch (encoding)
9804 {
9805 case eEncodingT1:
9806 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:�00�, 32);
9807 d = Bits32 (opcode, 11, 8);
9808 t = Bits32 (opcode, 15, 12);
9809 n = Bits32 (opcode, 19, 16);
9810 imm32 = Bits32 (opcode, 7, 0) << 2;
9811
9812 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
9813 if (BadReg (d) || BadReg (t) || (n == 15))
9814 return false;
9815
9816 // if d == n || d == t then UNPREDICTABLE;
9817 if ((d == n) || (d == t))
9818 return false;
9819
9820 break;
9821
9822 case eEncodingA1:
9823 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero offset
9824 d = Bits32 (opcode, 15, 12);
9825 t = Bits32 (opcode, 3, 0);
9826 n = Bits32 (opcode, 19, 16);
9827 imm32 = 0;
9828
9829 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
9830 if ((d == 15) || (t == 15) || (n == 15))
9831 return false;
9832
9833 // if d == n || d == t then UNPREDICTABLE;
9834 if ((d == n) || (d == t))
9835 return false;
9836
9837 break;
9838
9839 default:
9840 return false;
9841 }
9842
9843 // address = R[n] + imm32;
9844 uint32_t Rn = ReadCoreReg (n, &success);
9845 if (!success)
9846 return false;
9847
9848 addr_t address = Rn + imm32;
9849
9850 RegisterInfo base_reg;
9851 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9852 RegisterInfo data_reg;
9853 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
9854 EmulateInstruction::Context context;
9855 context.type = eContextRegisterStore;
9856 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, imm32);
9857
9858 // if ExclusiveMonitorsPass(address,4) then
9859 // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the sake of emulation, we will say this
9860 // always return true.
9861 if (true)
9862 {
9863 // MemA[address,4] = R[t];
9864 uint32_t Rt = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
9865 if (!success)
9866 return false;
9867
9868 if (!MemAWrite (context, address, Rt, addr_byte_size))
9869 return false;
9870
9871 // R[d] = 0;
9872 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0))
9873 return false;
9874 }
9875 else
9876 {
9877 // R[d] = 1;
9878 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
9879 return false;
9880 }
9881 }
9882 return true;
9883 }
9884
9885 // A8.6.197 STRB (immediate, ARM)
9886 bool
EmulateSTRBImmARM(const uint32_t opcode,const ARMEncoding encoding)9887 EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding)
9888 {
9889 #if 0
9890 if ConditionPassed() then
9891 EncodingSpecificOperations();
9892 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9893 address = if index then offset_addr else R[n];
9894 MemU[address,1] = R[t]<7:0>;
9895 if wback then R[n] = offset_addr;
9896 #endif
9897
9898 bool success = false;
9899
9900 if (ConditionPassed(opcode))
9901 {
9902 uint32_t t;
9903 uint32_t n;
9904 uint32_t imm32;
9905 bool index;
9906 bool add;
9907 bool wback;
9908
9909 switch (encoding)
9910 {
9911 case eEncodingA1:
9912 // if P == �0� && W == �1� then SEE STRBT;
9913 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9914 t = Bits32 (opcode, 15, 12);
9915 n = Bits32 (opcode, 19, 16);
9916 imm32 = Bits32 (opcode, 11, 0);
9917
9918 // index = (P == �1�); add = (U == �1�); wback = (P == �0�) || (W == �1�);
9919 index = BitIsSet (opcode, 24);
9920 add = BitIsSet (opcode, 23);
9921 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9922
9923 // if t == 15 then UNPREDICTABLE;
9924 if (t == 15)
9925 return false;
9926
9927 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9928 if (wback && ((n == 15) || (n == t)))
9929 return false;
9930
9931 break;
9932
9933 default:
9934 return false;
9935 }
9936
9937 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9938 uint32_t Rn = ReadCoreReg (n, &success);
9939 if (!success)
9940 return false;
9941
9942 addr_t offset_addr;
9943 if (add)
9944 offset_addr = Rn + imm32;
9945 else
9946 offset_addr = Rn - imm32;
9947
9948 // address = if index then offset_addr else R[n];
9949 addr_t address;
9950 if (index)
9951 address = offset_addr;
9952 else
9953 address = Rn;
9954
9955 // MemU[address,1] = R[t]<7:0>;
9956 uint32_t Rt = ReadCoreReg (t, &success);
9957 if (!success)
9958 return false;
9959
9960 RegisterInfo base_reg;
9961 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9962 RegisterInfo data_reg;
9963 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
9964 EmulateInstruction::Context context;
9965 context.type = eContextRegisterStore;
9966 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9967
9968 if (!MemUWrite (context, address, Bits32 (Rt, 7, 0), 1))
9969 return false;
9970
9971 // if wback then R[n] = offset_addr;
9972 if (wback)
9973 {
9974 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
9975 return false;
9976 }
9977 }
9978 return true;
9979 }
9980
9981 // A8.6.194 STR (immediate, ARM)
9982 bool
EmulateSTRImmARM(const uint32_t opcode,const ARMEncoding encoding)9983 EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding)
9984 {
9985 #if 0
9986 if ConditionPassed() then
9987 EncodingSpecificOperations();
9988 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9989 address = if index then offset_addr else R[n];
9990 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9991 if wback then R[n] = offset_addr;
9992 #endif
9993
9994 bool success = false;
9995
9996 if (ConditionPassed(opcode))
9997 {
9998 uint32_t t;
9999 uint32_t n;
10000 uint32_t imm32;
10001 bool index;
10002 bool add;
10003 bool wback;
10004
10005 const uint32_t addr_byte_size = GetAddressByteSize();
10006
10007 switch (encoding)
10008 {
10009 case eEncodingA1:
10010 // if P == �0� && W == �1� then SEE STRT;
10011 // if Rn == �1101� && P == �1� && U == �0� && W == �1� && imm12 == �000000000100� then SEE PUSH;
10012 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
10013 t = Bits32 (opcode, 15, 12);
10014 n = Bits32 (opcode, 19, 16);
10015 imm32 = Bits32 (opcode, 11, 0);
10016
10017 // index = (P == �1�); add = (U == �1�); wback = (P == �0�) || (W == �1�);
10018 index = BitIsSet (opcode, 24);
10019 add = BitIsSet (opcode, 23);
10020 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10021
10022 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
10023 if (wback && ((n == 15) || (n == t)))
10024 return false;
10025
10026 break;
10027
10028 default:
10029 return false;
10030 }
10031
10032 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10033 uint32_t Rn = ReadCoreReg (n, &success);
10034 if (!success)
10035 return false;
10036
10037 addr_t offset_addr;
10038 if (add)
10039 offset_addr = Rn + imm32;
10040 else
10041 offset_addr = Rn - imm32;
10042
10043 // address = if index then offset_addr else R[n];
10044 addr_t address;
10045 if (index)
10046 address = offset_addr;
10047 else
10048 address = Rn;
10049
10050 RegisterInfo base_reg;
10051 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10052 RegisterInfo data_reg;
10053 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
10054 EmulateInstruction::Context context;
10055 context.type = eContextRegisterStore;
10056 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10057
10058 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
10059 uint32_t Rt = ReadCoreReg (t, &success);
10060 if (!success)
10061 return false;
10062
10063 if (t == 15)
10064 {
10065 uint32_t pc_value = ReadCoreReg (PC_REG, &success);
10066 if (!success)
10067 return false;
10068
10069 if (!MemUWrite (context, address, pc_value, addr_byte_size))
10070 return false;
10071 }
10072 else
10073 {
10074 if (!MemUWrite (context, address, Rt, addr_byte_size))
10075 return false;
10076 }
10077
10078 // if wback then R[n] = offset_addr;
10079 if (wback)
10080 {
10081 context.type = eContextAdjustBaseRegister;
10082 context.SetImmediate (offset_addr);
10083
10084 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10085 return false;
10086 }
10087 }
10088 return true;
10089 }
10090
10091 // A8.6.66 LDRD (immediate)
10092 // Load Register Dual (immediate) calculates an address from a base register value and an immediate offset, loads two
10093 // words from memory, and writes them to two registers. It can use offset, post-indexed, or pre-indexed addressing.
10094 bool
EmulateLDRDImmediate(const uint32_t opcode,const ARMEncoding encoding)10095 EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding)
10096 {
10097 #if 0
10098 if ConditionPassed() then
10099 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10100 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10101 address = if index then offset_addr else R[n];
10102 R[t] = MemA[address,4];
10103 R[t2] = MemA[address+4,4];
10104 if wback then R[n] = offset_addr;
10105 #endif
10106
10107 bool success = false;
10108
10109 if (ConditionPassed(opcode))
10110 {
10111 uint32_t t;
10112 uint32_t t2;
10113 uint32_t n;
10114 uint32_t imm32;
10115 bool index;
10116 bool add;
10117 bool wback;
10118
10119 switch (encoding)
10120 {
10121 case eEncodingT1:
10122 //if P == �0� && W == �0� then SEE �Related encodings�;
10123 //if Rn == �1111� then SEE LDRD (literal);
10124 //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:�00�, 32);
10125 t = Bits32 (opcode, 15, 12);
10126 t2 = Bits32 (opcode, 11, 8);
10127 n = Bits32 (opcode, 19, 16);
10128 imm32 = Bits32 (opcode, 7, 0) << 2;
10129
10130 //index = (P == �1�); add = (U == �1�); wback = (W == �1�);
10131 index = BitIsSet (opcode, 24);
10132 add = BitIsSet (opcode, 23);
10133 wback = BitIsSet (opcode, 21);
10134
10135 //if wback && (n == t || n == t2) then UNPREDICTABLE;
10136 if (wback && ((n == t) || (n == t2)))
10137 return false;
10138
10139 //if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
10140 if (BadReg (t) || BadReg (t2) || (t == t2))
10141 return false;
10142
10143 break;
10144
10145 case eEncodingA1:
10146 //if Rn == �1111� then SEE LDRD (literal);
10147 //if Rt<0> == �1� then UNPREDICTABLE;
10148 //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
10149 t = Bits32 (opcode, 15, 12);
10150 if (BitIsSet (t, 0))
10151 return false;
10152 t2 = t + 1;
10153 n = Bits32 (opcode, 19, 16);
10154 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
10155
10156 //index = (P == �1�); add = (U == �1�); wback = (P == �0�) || (W == �1�);
10157 index = BitIsSet (opcode, 24);
10158 add = BitIsSet (opcode, 23);
10159 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10160
10161 //if P == �0� && W == �1� then UNPREDICTABLE;
10162 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10163 return false;
10164
10165 //if wback && (n == t || n == t2) then UNPREDICTABLE;
10166 if (wback && ((n == t) || (n == t2)))
10167 return false;
10168
10169 //if t2 == 15 then UNPREDICTABLE;
10170 if (t2 == 15)
10171 return false;
10172
10173 break;
10174
10175 default:
10176 return false;
10177 }
10178
10179 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10180 uint32_t Rn = ReadCoreReg (n, &success);
10181 if (!success)
10182 return false;
10183
10184 addr_t offset_addr;
10185 if (add)
10186 offset_addr = Rn + imm32;
10187 else
10188 offset_addr = Rn - imm32;
10189
10190 //address = if index then offset_addr else R[n];
10191 addr_t address;
10192 if (index)
10193 address = offset_addr;
10194 else
10195 address = Rn;
10196
10197 //R[t] = MemA[address,4];
10198 RegisterInfo base_reg;
10199 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10200
10201 EmulateInstruction::Context context;
10202 context.type = eContextRegisterLoad;
10203 context.SetRegisterPlusOffset (base_reg, address - Rn);
10204
10205 const uint32_t addr_byte_size = GetAddressByteSize();
10206 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10207 if (!success)
10208 return false;
10209
10210 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10211 return false;
10212
10213 //R[t2] = MemA[address+4,4];
10214
10215 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10216 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10217 if (!success)
10218 return false;
10219
10220 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10221 return false;
10222
10223 //if wback then R[n] = offset_addr;
10224 if (wback)
10225 {
10226 context.type = eContextAdjustBaseRegister;
10227 context.SetAddress (offset_addr);
10228
10229 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10230 return false;
10231 }
10232 }
10233 return true;
10234 }
10235
10236 // A8.6.68 LDRD (register)
10237 // Load Register Dual (register) calculates an address from a base register value and a register offset, loads two
10238 // words from memory, and writes them to two registers. It can use offset, post-indexed or pre-indexed addressing.
10239 bool
EmulateLDRDRegister(const uint32_t opcode,const ARMEncoding encoding)10240 EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding)
10241 {
10242 #if 0
10243 if ConditionPassed() then
10244 EncodingSpecificOperations();
10245 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10246 address = if index then offset_addr else R[n];
10247 R[t] = MemA[address,4];
10248 R[t2] = MemA[address+4,4];
10249 if wback then R[n] = offset_addr;
10250 #endif
10251
10252 bool success = false;
10253
10254 if (ConditionPassed(opcode))
10255 {
10256 uint32_t t;
10257 uint32_t t2;
10258 uint32_t n;
10259 uint32_t m;
10260 bool index;
10261 bool add;
10262 bool wback;
10263
10264 switch (encoding)
10265 {
10266 case eEncodingA1:
10267 // if Rt<0> == �1� then UNPREDICTABLE;
10268 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10269 t = Bits32 (opcode, 15, 12);
10270 if (BitIsSet (t, 0))
10271 return false;
10272 t2 = t + 1;
10273 n = Bits32 (opcode, 19, 16);
10274 m = Bits32 (opcode, 3, 0);
10275
10276 // index = (P == �1�); add = (U == �1�); wback = (P == �0�) || (W == �1�);
10277 index = BitIsSet (opcode, 24);
10278 add = BitIsSet (opcode, 23);
10279 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10280
10281 // if P == �0� && W == �1� then UNPREDICTABLE;
10282 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10283 return false;
10284
10285 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10286 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
10287 return false;
10288
10289 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10290 if (wback && ((n == 15) || (n == t) || (n == t2)))
10291 return false;
10292
10293 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10294 if ((ArchVersion() < 6) && wback && (m == n))
10295 return false;
10296 break;
10297
10298 default:
10299 return false;
10300 }
10301
10302 uint32_t Rn = ReadCoreReg (n, &success);
10303 if (!success)
10304 return false;
10305 RegisterInfo base_reg;
10306 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10307
10308 uint32_t Rm = ReadCoreReg (m, &success);
10309 if (!success)
10310 return false;
10311 RegisterInfo offset_reg;
10312 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
10313
10314 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10315 addr_t offset_addr;
10316 if (add)
10317 offset_addr = Rn + Rm;
10318 else
10319 offset_addr = Rn - Rm;
10320
10321 // address = if index then offset_addr else R[n];
10322 addr_t address;
10323 if (index)
10324 address = offset_addr;
10325 else
10326 address = Rn;
10327
10328 EmulateInstruction::Context context;
10329 context.type = eContextRegisterLoad;
10330 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
10331
10332 // R[t] = MemA[address,4];
10333 const uint32_t addr_byte_size = GetAddressByteSize();
10334 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10335 if (!success)
10336 return false;
10337
10338 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10339 return false;
10340
10341 // R[t2] = MemA[address+4,4];
10342
10343 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10344 if (!success)
10345 return false;
10346
10347 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10348 return false;
10349
10350 // if wback then R[n] = offset_addr;
10351 if (wback)
10352 {
10353 context.type = eContextAdjustBaseRegister;
10354 context.SetAddress (offset_addr);
10355
10356 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10357 return false;
10358 }
10359 }
10360 return true;
10361 }
10362
10363 // A8.6.200 STRD (immediate)
10364 // Store Register Dual (immediate) calculates an address from a base register value and an immediate offset, and
10365 // stores two words from two registers to memory. It can use offset, post-indexed, or pre-indexed addressing.
10366 bool
EmulateSTRDImm(const uint32_t opcode,const ARMEncoding encoding)10367 EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding)
10368 {
10369 #if 0
10370 if ConditionPassed() then
10371 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10372 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10373 address = if index then offset_addr else R[n];
10374 MemA[address,4] = R[t];
10375 MemA[address+4,4] = R[t2];
10376 if wback then R[n] = offset_addr;
10377 #endif
10378
10379 bool success = false;
10380
10381 if (ConditionPassed(opcode))
10382 {
10383 uint32_t t;
10384 uint32_t t2;
10385 uint32_t n;
10386 uint32_t imm32;
10387 bool index;
10388 bool add;
10389 bool wback;
10390
10391 switch (encoding)
10392 {
10393 case eEncodingT1:
10394 // if P == �0� && W == �0� then SEE �Related encodings�;
10395 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:�00�, 32);
10396 t = Bits32 (opcode, 15, 12);
10397 t2 = Bits32 (opcode, 11, 8);
10398 n = Bits32 (opcode, 19, 16);
10399 imm32 = Bits32 (opcode, 7, 0) << 2;
10400
10401 // index = (P == �1�); add = (U == �1�); wback = (W == �1�);
10402 index = BitIsSet (opcode, 24);
10403 add = BitIsSet (opcode, 23);
10404 wback = BitIsSet (opcode, 21);
10405
10406 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10407 if (wback && ((n == t) || (n == t2)))
10408 return false;
10409
10410 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
10411 if ((n == 15) || BadReg (t) || BadReg (t2))
10412 return false;
10413
10414 break;
10415
10416 case eEncodingA1:
10417 // if Rt<0> == �1� then UNPREDICTABLE;
10418 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
10419 t = Bits32 (opcode, 15, 12);
10420 if (BitIsSet (t, 0))
10421 return false;
10422
10423 t2 = t + 1;
10424 n = Bits32 (opcode, 19, 16);
10425 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
10426
10427 // index = (P == �1�); add = (U == �1�); wback = (P == �0�) || (W == �1�);
10428 index = BitIsSet (opcode, 24);
10429 add = BitIsSet (opcode, 23);
10430 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10431
10432 // if P == �0� && W == �1� then UNPREDICTABLE;
10433 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10434 return false;
10435
10436 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10437 if (wback && ((n == 15) || (n == t) || (n == t2)))
10438 return false;
10439
10440 // if t2 == 15 then UNPREDICTABLE;
10441 if (t2 == 15)
10442 return false;
10443
10444 break;
10445
10446 default:
10447 return false;
10448 }
10449
10450 RegisterInfo base_reg;
10451 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10452
10453 uint32_t Rn = ReadCoreReg (n, &success);
10454 if (!success)
10455 return false;
10456
10457 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10458 addr_t offset_addr;
10459 if (add)
10460 offset_addr = Rn + imm32;
10461 else
10462 offset_addr = Rn - imm32;
10463
10464 //address = if index then offset_addr else R[n];
10465 addr_t address;
10466 if (index)
10467 address = offset_addr;
10468 else
10469 address = Rn;
10470
10471 //MemA[address,4] = R[t];
10472 RegisterInfo data_reg;
10473 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
10474
10475 uint32_t data = ReadCoreReg (t, &success);
10476 if (!success)
10477 return false;
10478
10479 EmulateInstruction::Context context;
10480 context.type = eContextRegisterStore;
10481 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10482
10483 const uint32_t addr_byte_size = GetAddressByteSize();
10484
10485 if (!MemAWrite (context, address, data, addr_byte_size))
10486 return false;
10487
10488 //MemA[address+4,4] = R[t2];
10489 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
10490 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10491
10492 data = ReadCoreReg (t2, &success);
10493 if (!success)
10494 return false;
10495
10496 if (!MemAWrite (context, address + 4, data, addr_byte_size))
10497 return false;
10498
10499 //if wback then R[n] = offset_addr;
10500 if (wback)
10501 {
10502 context.type = eContextAdjustBaseRegister;
10503 context.SetAddress (offset_addr);
10504
10505 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10506 return false;
10507 }
10508 }
10509 return true;
10510 }
10511
10512
10513 // A8.6.201 STRD (register)
10514 bool
EmulateSTRDReg(const uint32_t opcode,const ARMEncoding encoding)10515 EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding)
10516 {
10517 #if 0
10518 if ConditionPassed() then
10519 EncodingSpecificOperations();
10520 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10521 address = if index then offset_addr else R[n];
10522 MemA[address,4] = R[t];
10523 MemA[address+4,4] = R[t2];
10524 if wback then R[n] = offset_addr;
10525 #endif
10526
10527 bool success = false;
10528
10529 if (ConditionPassed(opcode))
10530 {
10531 uint32_t t;
10532 uint32_t t2;
10533 uint32_t n;
10534 uint32_t m;
10535 bool index;
10536 bool add;
10537 bool wback;
10538
10539 switch (encoding)
10540 {
10541 case eEncodingA1:
10542 // if Rt<0> == �1� then UNPREDICTABLE;
10543 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10544 t = Bits32 (opcode, 15, 12);
10545 if (BitIsSet (t, 0))
10546 return false;
10547
10548 t2 = t+1;
10549 n = Bits32 (opcode, 19, 16);
10550 m = Bits32 (opcode, 3, 0);
10551
10552 // index = (P == �1�); add = (U == �1�); wback = (P == �0�) || (W == �1�);
10553 index = BitIsSet (opcode, 24);
10554 add = BitIsSet (opcode, 23);
10555 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10556
10557 // if P == �0� && W == �1� then UNPREDICTABLE;
10558 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10559 return false;
10560
10561 // if t2 == 15 || m == 15 then UNPREDICTABLE;
10562 if ((t2 == 15) || (m == 15))
10563 return false;
10564
10565 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10566 if (wback && ((n == 15) || (n == t) || (n == t2)))
10567 return false;
10568
10569 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10570 if ((ArchVersion() < 6) && wback && (m == n))
10571 return false;
10572
10573 break;
10574
10575 default:
10576 return false;
10577 }
10578
10579 RegisterInfo base_reg;
10580 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10581 RegisterInfo offset_reg;
10582 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
10583 RegisterInfo data_reg;
10584
10585 uint32_t Rn = ReadCoreReg (n, &success);
10586 if (!success)
10587 return false;
10588
10589 uint32_t Rm = ReadCoreReg (m, &success);
10590 if (!success)
10591 return false;
10592
10593 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10594 addr_t offset_addr;
10595 if (add)
10596 offset_addr = Rn + Rm;
10597 else
10598 offset_addr = Rn - Rm;
10599
10600 // address = if index then offset_addr else R[n];
10601 addr_t address;
10602 if (index)
10603 address = offset_addr;
10604 else
10605 address = Rn;
10606 // MemA[address,4] = R[t];
10607 uint32_t Rt = ReadCoreReg (t, &success);
10608 if (!success)
10609 return false;
10610
10611 EmulateInstruction::Context context;
10612 context.type = eContextRegisterStore;
10613 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
10614 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10615
10616 const uint32_t addr_byte_size = GetAddressByteSize();
10617
10618 if (!MemAWrite (context, address, Rt, addr_byte_size))
10619 return false;
10620
10621 // MemA[address+4,4] = R[t2];
10622 uint32_t Rt2 = ReadCoreReg (t2, &success);
10623 if (!success)
10624 return false;
10625
10626 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
10627
10628 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10629
10630 if (!MemAWrite (context, address + 4, Rt2, addr_byte_size))
10631 return false;
10632
10633 // if wback then R[n] = offset_addr;
10634 if (wback)
10635 {
10636 context.type = eContextAdjustBaseRegister;
10637 context.SetAddress (offset_addr);
10638
10639 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10640 return false;
10641
10642 }
10643 }
10644 return true;
10645 }
10646
10647 // A8.6.319 VLDM
10648 // Vector Load Multiple loads multiple extension registers from consecutive memory locations using an address from
10649 // an ARM core register.
10650 bool
EmulateVLDM(const uint32_t opcode,const ARMEncoding encoding)10651 EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding encoding)
10652 {
10653 #if 0
10654 if ConditionPassed() then
10655 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10656 address = if add then R[n] else R[n]-imm32;
10657 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
10658 for r = 0 to regs-1
10659 if single_regs then
10660 S[d+r] = MemA[address,4]; address = address+4;
10661 else
10662 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10663 // Combine the word-aligned words in the correct order for current endianness.
10664 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10665 #endif
10666
10667 bool success = false;
10668
10669 if (ConditionPassed(opcode))
10670 {
10671 bool single_regs;
10672 bool add;
10673 bool wback;
10674 uint32_t d;
10675 uint32_t n;
10676 uint32_t imm32;
10677 uint32_t regs;
10678
10679 switch (encoding)
10680 {
10681 case eEncodingT1:
10682 case eEncodingA1:
10683 // if P == �0� && U == �0� && W == �0� then SEE �Related encodings�;
10684 // if P == �0� && U == �1� && W == �1� && Rn == �1101� then SEE VPOP;
10685 // if P == �1� && W == �0� then SEE VLDR;
10686 // if P == U && W == �1� then UNDEFINED;
10687 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10688 return false;
10689
10690 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10691 // single_regs = FALSE; add = (U == �1�); wback = (W == �1�);
10692 single_regs = false;
10693 add = BitIsSet (opcode, 23);
10694 wback = BitIsSet (opcode, 21);
10695
10696 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:�00�, 32);
10697 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10698 n = Bits32 (opcode, 19, 16);
10699 imm32 = Bits32 (opcode, 7, 0) << 2;
10700
10701 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see �FLDMX�.
10702 regs = Bits32 (opcode, 7, 0) / 2;
10703
10704 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10705 if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
10706 return false;
10707
10708 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10709 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10710 return false;
10711
10712 break;
10713
10714 case eEncodingT2:
10715 case eEncodingA2:
10716 // if P == �0� && U == �0� && W == �0� then SEE �Related encodings�;
10717 // if P == �0� && U == �1� && W == �1� && Rn == �1101� then SEE VPOP;
10718 // if P == �1� && W == �0� then SEE VLDR;
10719 // if P == U && W == �1� then UNDEFINED;
10720 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10721 return false;
10722
10723 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10724 // single_regs = TRUE; add = (U == �1�); wback = (W == �1�); d = UInt(Vd:D); n = UInt(Rn);
10725 single_regs = true;
10726 add = BitIsSet (opcode, 23);
10727 wback = BitIsSet (opcode, 21);
10728 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10729 n = Bits32 (opcode, 19, 16);
10730
10731 // imm32 = ZeroExtend(imm8:�00�, 32); regs = UInt(imm8);
10732 imm32 = Bits32 (opcode, 7, 0) << 2;
10733 regs = Bits32 (opcode, 7, 0);
10734
10735 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10736 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10737 return false;
10738
10739 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10740 if ((regs == 0) || ((d + regs) > 32))
10741 return false;
10742 break;
10743
10744 default:
10745 return false;
10746 }
10747
10748 RegisterInfo base_reg;
10749 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10750
10751 uint32_t Rn = ReadCoreReg (n, &success);
10752 if (!success)
10753 return false;
10754
10755 // address = if add then R[n] else R[n]-imm32;
10756 addr_t address;
10757 if (add)
10758 address = Rn;
10759 else
10760 address = Rn - imm32;
10761
10762 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
10763 EmulateInstruction::Context context;
10764
10765 if (wback)
10766 {
10767 uint32_t value;
10768 if (add)
10769 value = Rn + imm32;
10770 else
10771 value = Rn - imm32;
10772
10773 context.type = eContextAdjustBaseRegister;
10774 context.SetImmediateSigned (value - Rn);
10775 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10776 return false;
10777
10778 }
10779
10780 const uint32_t addr_byte_size = GetAddressByteSize();
10781 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10782
10783 context.type = eContextRegisterLoad;
10784
10785 // for r = 0 to regs-1
10786 for (uint32_t r = 0; r < regs; ++r)
10787 {
10788 if (single_regs)
10789 {
10790 // S[d+r] = MemA[address,4]; address = address+4;
10791 context.SetRegisterPlusOffset (base_reg, address - Rn);
10792
10793 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10794 if (!success)
10795 return false;
10796
10797 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10798 return false;
10799
10800 address = address + 4;
10801 }
10802 else
10803 {
10804 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10805 context.SetRegisterPlusOffset (base_reg, address - Rn);
10806 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
10807 if (!success)
10808 return false;
10809
10810 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10811 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
10812 if (!success)
10813 return false;
10814
10815 address = address + 8;
10816 // // Combine the word-aligned words in the correct order for current endianness.
10817 // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10818 uint64_t data;
10819 if (GetByteOrder() == eByteOrderBig)
10820 {
10821 data = word1;
10822 data = (data << 32) | word2;
10823 }
10824 else
10825 {
10826 data = word2;
10827 data = (data << 32) | word1;
10828 }
10829
10830 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10831 return false;
10832 }
10833 }
10834 }
10835 return true;
10836 }
10837
10838 // A8.6.399 VSTM
10839 // Vector Store Multiple stores multiple extension registers to consecutive memory locations using an address from an
10840 // ARM core register.
10841 bool
EmulateVSTM(const uint32_t opcode,const ARMEncoding encoding)10842 EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding encoding)
10843 {
10844 #if 0
10845 if ConditionPassed() then
10846 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10847 address = if add then R[n] else R[n]-imm32;
10848 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
10849 for r = 0 to regs-1
10850 if single_regs then
10851 MemA[address,4] = S[d+r]; address = address+4;
10852 else
10853 // Store as two word-aligned words in the correct order for current endianness.
10854 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10855 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10856 address = address+8;
10857 #endif
10858
10859 bool success = false;
10860
10861 if (ConditionPassed (opcode))
10862 {
10863 bool single_regs;
10864 bool add;
10865 bool wback;
10866 uint32_t d;
10867 uint32_t n;
10868 uint32_t imm32;
10869 uint32_t regs;
10870
10871 switch (encoding)
10872 {
10873 case eEncodingT1:
10874 case eEncodingA1:
10875 // if P == �0� && U == �0� && W == �0� then SEE �Related encodings�;
10876 // if P == �1� && U == �0� && W == �1� && Rn == �1101� then SEE VPUSH;
10877 // if P == �1� && W == �0� then SEE VSTR;
10878 // if P == U && W == �1� then UNDEFINED;
10879 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10880 return false;
10881
10882 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10883 // single_regs = FALSE; add = (U == �1�); wback = (W == �1�);
10884 single_regs = false;
10885 add = BitIsSet (opcode, 23);
10886 wback = BitIsSet (opcode, 21);
10887
10888 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:�00�, 32);
10889 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10890 n = Bits32 (opcode, 19, 16);
10891 imm32 = Bits32 (opcode, 7, 0) << 2;
10892
10893 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see �FSTMX�.
10894 regs = Bits32 (opcode, 7, 0) / 2;
10895
10896 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10897 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10898 return false;
10899
10900 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10901 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10902 return false;
10903
10904 break;
10905
10906 case eEncodingT2:
10907 case eEncodingA2:
10908 // if P == �0� && U == �0� && W == �0� then SEE �Related encodings�;
10909 // if P == �1� && U == �0� && W == �1� && Rn == �1101� then SEE VPUSH;
10910 // if P == �1� && W == �0� then SEE VSTR;
10911 // if P == U && W == �1� then UNDEFINED;
10912 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10913 return false;
10914
10915 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10916 // single_regs = TRUE; add = (U == �1�); wback = (W == �1�); d = UInt(Vd:D); n = UInt(Rn);
10917 single_regs = true;
10918 add = BitIsSet (opcode, 23);
10919 wback = BitIsSet (opcode, 21);
10920 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10921 n = Bits32 (opcode, 19, 16);
10922
10923 // imm32 = ZeroExtend(imm8:�00�, 32); regs = UInt(imm8);
10924 imm32 = Bits32 (opcode, 7, 0) << 2;
10925 regs = Bits32 (opcode, 7, 0);
10926
10927 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10928 if ((n == 15) && (wback || (CurrentInstrSet () != eModeARM)))
10929 return false;
10930
10931 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10932 if ((regs == 0) || ((d + regs) > 32))
10933 return false;
10934
10935 break;
10936
10937 default:
10938 return false;
10939 }
10940
10941 RegisterInfo base_reg;
10942 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10943
10944 uint32_t Rn = ReadCoreReg (n, &success);
10945 if (!success)
10946 return false;
10947
10948 // address = if add then R[n] else R[n]-imm32;
10949 addr_t address;
10950 if (add)
10951 address = Rn;
10952 else
10953 address = Rn - imm32;
10954
10955 EmulateInstruction::Context context;
10956 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
10957 if (wback)
10958 {
10959 uint32_t value;
10960 if (add)
10961 value = Rn + imm32;
10962 else
10963 value = Rn - imm32;
10964
10965 context.type = eContextAdjustBaseRegister;
10966 context.SetRegisterPlusOffset (base_reg, value - Rn);
10967
10968 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10969 return false;
10970 }
10971
10972 const uint32_t addr_byte_size = GetAddressByteSize();
10973 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10974
10975 context.type = eContextRegisterStore;
10976 // for r = 0 to regs-1
10977 for (uint32_t r = 0; r < regs; ++r)
10978 {
10979
10980 if (single_regs)
10981 {
10982 // MemA[address,4] = S[d+r]; address = address+4;
10983 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10984 if (!success)
10985 return false;
10986
10987 RegisterInfo data_reg;
10988 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg);
10989 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10990 if (!MemAWrite (context, address, data, addr_byte_size))
10991 return false;
10992
10993 address = address + 4;
10994 }
10995 else
10996 {
10997 // // Store as two word-aligned words in the correct order for current endianness.
10998 // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10999 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
11000 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
11001 if (!success)
11002 return false;
11003
11004 RegisterInfo data_reg;
11005 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg);
11006
11007 if (GetByteOrder() == eByteOrderBig)
11008 {
11009 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11010 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
11011 return false;
11012
11013 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11014 if (!MemAWrite (context, address+ 4, Bits64 (data, 31, 0), addr_byte_size))
11015 return false;
11016 }
11017 else
11018 {
11019 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11020 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
11021 return false;
11022
11023 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11024 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
11025 return false;
11026 }
11027 // address = address+8;
11028 address = address + 8;
11029 }
11030 }
11031 }
11032 return true;
11033 }
11034
11035 // A8.6.320
11036 // This instruciton loads a single extension register fronm memory, using an address from an ARM core register, with
11037 // an optional offset.
11038 bool
EmulateVLDR(const uint32_t opcode,ARMEncoding encoding)11039 EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding)
11040 {
11041 #if 0
11042 if ConditionPassed() then
11043 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11044 base = if n == 15 then Align(PC,4) else R[n];
11045 address = if add then (base + imm32) else (base - imm32);
11046 if single_reg then
11047 S[d] = MemA[address,4];
11048 else
11049 word1 = MemA[address,4]; word2 = MemA[address+4,4];
11050 // Combine the word-aligned words in the correct order for current endianness.
11051 D[d] = if BigEndian() then word1:word2 else word2:word1;
11052 #endif
11053
11054 bool success = false;
11055
11056 if (ConditionPassed (opcode))
11057 {
11058 bool single_reg;
11059 bool add;
11060 uint32_t imm32;
11061 uint32_t d;
11062 uint32_t n;
11063
11064 switch (encoding)
11065 {
11066 case eEncodingT1:
11067 case eEncodingA1:
11068 // single_reg = FALSE; add = (U == �1�); imm32 = ZeroExtend(imm8:�00�, 32);
11069 single_reg = false;
11070 add = BitIsSet (opcode, 23);
11071 imm32 = Bits32 (opcode, 7, 0) << 2;
11072
11073 // d = UInt(D:Vd); n = UInt(Rn);
11074 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11075 n = Bits32 (opcode, 19, 16);
11076
11077 break;
11078
11079 case eEncodingT2:
11080 case eEncodingA2:
11081 // single_reg = TRUE; add = (U == �1�); imm32 = ZeroExtend(imm8:�00�, 32);
11082 single_reg = true;
11083 add = BitIsSet (opcode, 23);
11084 imm32 = Bits32 (opcode, 7, 0) << 2;
11085
11086 // d = UInt(Vd:D); n = UInt(Rn);
11087 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
11088 n = Bits32 (opcode, 19, 16);
11089
11090 break;
11091
11092 default:
11093 return false;
11094 }
11095 RegisterInfo base_reg;
11096 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11097
11098 uint32_t Rn = ReadCoreReg (n, &success);
11099 if (!success)
11100 return false;
11101
11102 // base = if n == 15 then Align(PC,4) else R[n];
11103 uint32_t base;
11104 if (n == 15)
11105 base = AlignPC (Rn);
11106 else
11107 base = Rn;
11108
11109 // address = if add then (base + imm32) else (base - imm32);
11110 addr_t address;
11111 if (add)
11112 address = base + imm32;
11113 else
11114 address = base - imm32;
11115
11116 const uint32_t addr_byte_size = GetAddressByteSize();
11117 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11118
11119 EmulateInstruction::Context context;
11120 context.type = eContextRegisterLoad;
11121 context.SetRegisterPlusOffset (base_reg, address - base);
11122
11123 if (single_reg)
11124 {
11125 // S[d] = MemA[address,4];
11126 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
11127 if (!success)
11128 return false;
11129
11130 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data))
11131 return false;
11132 }
11133 else
11134 {
11135 // word1 = MemA[address,4]; word2 = MemA[address+4,4];
11136 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
11137 if (!success)
11138 return false;
11139
11140 context.SetRegisterPlusOffset (base_reg, (address + 4) - base);
11141 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
11142 if (!success)
11143 return false;
11144 // // Combine the word-aligned words in the correct order for current endianness.
11145 // D[d] = if BigEndian() then word1:word2 else word2:word1;
11146 uint64_t data64;
11147 if (GetByteOrder() == eByteOrderBig)
11148 {
11149 data64 = word1;
11150 data64 = (data64 << 32) | word2;
11151 }
11152 else
11153 {
11154 data64 = word2;
11155 data64 = (data64 << 32) | word1;
11156 }
11157
11158 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data64))
11159 return false;
11160 }
11161 }
11162 return true;
11163 }
11164
11165 // A8.6.400 VSTR
11166 // This instruction stores a signle extension register to memory, using an address from an ARM core register, with an
11167 // optional offset.
11168 bool
EmulateVSTR(const uint32_t opcode,ARMEncoding encoding)11169 EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding)
11170 {
11171 #if 0
11172 if ConditionPassed() then
11173 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11174 address = if add then (R[n] + imm32) else (R[n] - imm32);
11175 if single_reg then
11176 MemA[address,4] = S[d];
11177 else
11178 // Store as two word-aligned words in the correct order for current endianness.
11179 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11180 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11181 #endif
11182
11183 bool success = false;
11184
11185 if (ConditionPassed (opcode))
11186 {
11187 bool single_reg;
11188 bool add;
11189 uint32_t imm32;
11190 uint32_t d;
11191 uint32_t n;
11192
11193 switch (encoding)
11194 {
11195 case eEncodingT1:
11196 case eEncodingA1:
11197 // single_reg = FALSE; add = (U == �1�); imm32 = ZeroExtend(imm8:�00�, 32);
11198 single_reg = false;
11199 add = BitIsSet (opcode, 23);
11200 imm32 = Bits32 (opcode, 7, 0) << 2;
11201
11202 // d = UInt(D:Vd); n = UInt(Rn);
11203 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11204 n = Bits32 (opcode, 19, 16);
11205
11206 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11207 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11208 return false;
11209
11210 break;
11211
11212 case eEncodingT2:
11213 case eEncodingA2:
11214 // single_reg = TRUE; add = (U == �1�); imm32 = ZeroExtend(imm8:�00�, 32);
11215 single_reg = true;
11216 add = BitIsSet (opcode, 23);
11217 imm32 = Bits32 (opcode, 7, 0) << 2;
11218
11219 // d = UInt(Vd:D); n = UInt(Rn);
11220 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
11221 n = Bits32 (opcode, 19, 16);
11222
11223 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11224 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11225 return false;
11226
11227 break;
11228
11229 default:
11230 return false;
11231 }
11232
11233 RegisterInfo base_reg;
11234 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11235
11236 uint32_t Rn = ReadCoreReg (n, &success);
11237 if (!success)
11238 return false;
11239
11240 // address = if add then (R[n] + imm32) else (R[n] - imm32);
11241 addr_t address;
11242 if (add)
11243 address = Rn + imm32;
11244 else
11245 address = Rn - imm32;
11246
11247 const uint32_t addr_byte_size = GetAddressByteSize();
11248 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11249
11250 RegisterInfo data_reg;
11251 GetRegisterInfo (eRegisterKindDWARF, start_reg + d, data_reg);
11252 EmulateInstruction::Context context;
11253 context.type = eContextRegisterStore;
11254 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11255
11256 if (single_reg)
11257 {
11258 // MemA[address,4] = S[d];
11259 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11260 if (!success)
11261 return false;
11262
11263 if (!MemAWrite (context, address, data, addr_byte_size))
11264 return false;
11265 }
11266 else
11267 {
11268 // // Store as two word-aligned words in the correct order for current endianness.
11269 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11270 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11271 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11272 if (!success)
11273 return false;
11274
11275 if (GetByteOrder() == eByteOrderBig)
11276 {
11277 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
11278 return false;
11279
11280 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11281 if (!MemAWrite (context, address + 4, Bits64 (data, 31, 0), addr_byte_size))
11282 return false;
11283 }
11284 else
11285 {
11286 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
11287 return false;
11288
11289 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11290 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
11291 return false;
11292 }
11293 }
11294 }
11295 return true;
11296 }
11297
11298 // A8.6.307 VLDI1 (multiple single elements)
11299 // This instruction loads elements from memory into one, two, three or four registers, without de-interleaving. Every
11300 // element of each register is loaded.
11301 bool
EmulateVLD1Multiple(const uint32_t opcode,ARMEncoding encoding)11302 EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding encoding)
11303 {
11304 #if 0
11305 if ConditionPassed() then
11306 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11307 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11308 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11309 for r = 0 to regs-1
11310 for e = 0 to elements-1
11311 Elem[D[d+r],e,esize] = MemU[address,ebytes];
11312 address = address + ebytes;
11313 #endif
11314
11315 bool success = false;
11316
11317 if (ConditionPassed (opcode))
11318 {
11319 uint32_t regs;
11320 uint32_t alignment;
11321 uint32_t ebytes;
11322 uint32_t esize;
11323 uint32_t elements;
11324 uint32_t d;
11325 uint32_t n;
11326 uint32_t m;
11327 bool wback;
11328 bool register_index;
11329
11330 switch (encoding)
11331 {
11332 case eEncodingT1:
11333 case eEncodingA1:
11334 {
11335 // case type of
11336 // when �0111�
11337 // regs = 1; if align<1> == �1� then UNDEFINED;
11338 // when �1010�
11339 // regs = 2; if align == �11� then UNDEFINED;
11340 // when �0110�
11341 // regs = 3; if align<1> == �1� then UNDEFINED;
11342 // when �0010�
11343 // regs = 4;
11344 // otherwise
11345 // SEE �Related encodings�;
11346 uint32_t type = Bits32 (opcode, 11, 8);
11347 uint32_t align = Bits32 (opcode, 5, 4);
11348 if (type == 7) // '0111'
11349 {
11350 regs = 1;
11351 if (BitIsSet (align, 1))
11352 return false;
11353 }
11354 else if (type == 10) // '1010'
11355 {
11356 regs = 2;
11357 if (align == 3)
11358 return false;
11359
11360 }
11361 else if (type == 6) // '0110'
11362 {
11363 regs = 3;
11364 if (BitIsSet (align, 1))
11365 return false;
11366 }
11367 else if (type == 2) // '0010'
11368 {
11369 regs = 4;
11370 }
11371 else
11372 return false;
11373
11374 // alignment = if align == �00� then 1 else 4 << UInt(align);
11375 if (align == 0)
11376 alignment = 1;
11377 else
11378 alignment = 4 << align;
11379
11380 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11381 ebytes = 1 << Bits32 (opcode, 7, 6);
11382 esize = 8 * ebytes;
11383 elements = 8 / ebytes;
11384
11385 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11386 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11387 n = Bits32 (opcode, 19, 15);
11388 m = Bits32 (opcode, 3, 0);
11389
11390 // wback = (m != 15); register_index = (m != 15 && m != 13);
11391 wback = (m != 15);
11392 register_index = ((m != 15) && (m != 13));
11393
11394 // if d+regs > 32 then UNPREDICTABLE;
11395 if ((d + regs) > 32)
11396 return false;
11397 }
11398 break;
11399
11400 default:
11401 return false;
11402 }
11403
11404 RegisterInfo base_reg;
11405 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11406
11407 uint32_t Rn = ReadCoreReg (n, &success);
11408 if (!success)
11409 return false;
11410
11411 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11412 addr_t address = Rn;
11413 if ((address % alignment) != 0)
11414 return false;
11415
11416 EmulateInstruction::Context context;
11417 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11418 if (wback)
11419 {
11420 uint32_t Rm = ReadCoreReg (m, &success);
11421 if (!success)
11422 return false;
11423
11424 uint32_t offset;
11425 if (register_index)
11426 offset = Rm;
11427 else
11428 offset = 8 * regs;
11429
11430 uint32_t value = Rn + offset;
11431 context.type = eContextAdjustBaseRegister;
11432 context.SetRegisterPlusOffset (base_reg, offset);
11433
11434 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11435 return false;
11436
11437 }
11438
11439 // for r = 0 to regs-1
11440 for (uint32_t r = 0; r < regs; ++r)
11441 {
11442 // for e = 0 to elements-1
11443 uint64_t assembled_data = 0;
11444 for (uint32_t e = 0; e < elements; ++e)
11445 {
11446 // Elem[D[d+r],e,esize] = MemU[address,ebytes];
11447 context.type = eContextRegisterLoad;
11448 context.SetRegisterPlusOffset (base_reg, address - Rn);
11449 uint64_t data = MemURead (context, address, ebytes, 0, &success);
11450 if (!success)
11451 return false;
11452
11453 assembled_data = (data << (e * esize)) | assembled_data; // New data goes to the left of existing data
11454
11455 // address = address + ebytes;
11456 address = address + ebytes;
11457 }
11458 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, assembled_data))
11459 return false;
11460 }
11461 }
11462 return true;
11463 }
11464
11465 // A8.6.308 VLD1 (single element to one lane)
11466 //
11467 bool
EmulateVLD1Single(const uint32_t opcode,const ARMEncoding encoding)11468 EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncoding encoding)
11469 {
11470 #if 0
11471 if ConditionPassed() then
11472 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11473 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11474 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11475 Elem[D[d],index,esize] = MemU[address,ebytes];
11476 #endif
11477
11478 bool success = false;
11479
11480 if (ConditionPassed (opcode))
11481 {
11482 uint32_t ebytes;
11483 uint32_t esize;
11484 uint32_t index;
11485 uint32_t alignment;
11486 uint32_t d;
11487 uint32_t n;
11488 uint32_t m;
11489 bool wback;
11490 bool register_index;
11491
11492 switch (encoding)
11493 {
11494 case eEncodingT1:
11495 case eEncodingA1:
11496 {
11497 uint32_t size = Bits32 (opcode, 11, 10);
11498 uint32_t index_align = Bits32 (opcode, 7, 4);
11499 // if size == �11� then SEE VLD1 (single element to all lanes);
11500 if (size == 3)
11501 return EmulateVLD1SingleAll (opcode, encoding);
11502 // case size of
11503 if (size == 0) // when '00'
11504 {
11505 // if index_align<0> != �0� then UNDEFINED;
11506 if (BitIsClear (index_align, 0))
11507 return false;
11508
11509 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11510 ebytes = 1;
11511 esize = 8;
11512 index = Bits32 (index_align, 3, 1);
11513 alignment = 1;
11514 }
11515 else if (size == 1) // when �01�
11516 {
11517 // if index_align<1> != �0� then UNDEFINED;
11518 if (BitIsClear (index_align, 1))
11519 return false;
11520
11521 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11522 ebytes = 2;
11523 esize = 16;
11524 index = Bits32 (index_align, 3, 2);
11525
11526 // alignment = if index_align<0> == �0� then 1 else 2;
11527 if (BitIsClear (index_align, 0))
11528 alignment = 1;
11529 else
11530 alignment = 2;
11531 }
11532 else if (size == 2) // when �10�
11533 {
11534 // if index_align<2> != �0� then UNDEFINED;
11535 if (BitIsClear (index_align, 2))
11536 return false;
11537
11538 // if index_align<1:0> != �00� && index_align<1:0> != �11� then UNDEFINED;
11539 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11540 return false;
11541
11542 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11543 ebytes = 4;
11544 esize = 32;
11545 index = Bit32 (index_align, 3);
11546
11547 // alignment = if index_align<1:0> == �00� then 1 else 4;
11548 if (Bits32 (index_align, 1, 0) == 0)
11549 alignment = 1;
11550 else
11551 alignment = 4;
11552 }
11553 else
11554 {
11555 return false;
11556 }
11557 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11558 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11559 n = Bits32 (opcode, 19, 16);
11560 m = Bits32 (opcode, 3, 0);
11561
11562 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11563 wback = (m != 15);
11564 register_index = ((m != 15) && (m != 13));
11565
11566 if (n == 15)
11567 return false;
11568
11569 }
11570 break;
11571
11572 default:
11573 return false;
11574 }
11575
11576 RegisterInfo base_reg;
11577 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11578
11579 uint32_t Rn = ReadCoreReg (n, &success);
11580 if (!success)
11581 return false;
11582
11583 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11584 addr_t address = Rn;
11585 if ((address % alignment) != 0)
11586 return false;
11587
11588 EmulateInstruction::Context context;
11589 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11590 if (wback)
11591 {
11592 uint32_t Rm = ReadCoreReg (m, &success);
11593 if (!success)
11594 return false;
11595
11596 uint32_t offset;
11597 if (register_index)
11598 offset = Rm;
11599 else
11600 offset = ebytes;
11601
11602 uint32_t value = Rn + offset;
11603
11604 context.type = eContextAdjustBaseRegister;
11605 context.SetRegisterPlusOffset (base_reg, offset);
11606
11607 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11608 return false;
11609 }
11610
11611 // Elem[D[d],index,esize] = MemU[address,ebytes];
11612 uint32_t element = MemURead (context, address, esize, 0, &success);
11613 if (!success)
11614 return false;
11615
11616 element = element << (index * esize);
11617
11618 uint64_t reg_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11619 if (!success)
11620 return false;
11621
11622 uint64_t all_ones = -1;
11623 uint64_t mask = all_ones << ((index+1) * esize); // mask is all 1's to left of where 'element' goes, & all 0's
11624 // at element & to the right of element.
11625 if (index > 0)
11626 mask = mask | Bits64 (all_ones, (index * esize) - 1, 0); // add 1's to the right of where 'element' goes.
11627 // now mask should be 0's where element goes & 1's
11628 // everywhere else.
11629
11630 uint64_t masked_reg = reg_data & mask; // Take original reg value & zero out 'element' bits
11631 reg_data = masked_reg & element; // Put 'element' into those bits in reg_data.
11632
11633 context.type = eContextRegisterLoad;
11634 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, reg_data))
11635 return false;
11636 }
11637 return true;
11638 }
11639
11640 // A8.6.391 VST1 (multiple single elements)
11641 // Vector Store (multiple single elements) stores elements to memory from one, two, three, or four regsiters, without
11642 // interleaving. Every element of each register is stored.
11643 bool
EmulateVST1Multiple(const uint32_t opcode,ARMEncoding encoding)11644 EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding encoding)
11645 {
11646 #if 0
11647 if ConditionPassed() then
11648 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11649 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11650 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11651 for r = 0 to regs-1
11652 for e = 0 to elements-1
11653 MemU[address,ebytes] = Elem[D[d+r],e,esize];
11654 address = address + ebytes;
11655 #endif
11656
11657 bool success = false;
11658
11659 if (ConditionPassed (opcode))
11660 {
11661 uint32_t regs;
11662 uint32_t alignment;
11663 uint32_t ebytes;
11664 uint32_t esize;
11665 uint32_t elements;
11666 uint32_t d;
11667 uint32_t n;
11668 uint32_t m;
11669 bool wback;
11670 bool register_index;
11671
11672 switch (encoding)
11673 {
11674 case eEncodingT1:
11675 case eEncodingA1:
11676 {
11677 uint32_t type = Bits32 (opcode, 11, 8);
11678 uint32_t align = Bits32 (opcode, 5, 4);
11679
11680 // case type of
11681 if (type == 7) // when �0111�
11682 {
11683 // regs = 1; if align<1> == �1� then UNDEFINED;
11684 regs = 1;
11685 if (BitIsSet (align, 1))
11686 return false;
11687 }
11688 else if (type == 10) // when �1010�
11689 {
11690 // regs = 2; if align == �11� then UNDEFINED;
11691 regs = 2;
11692 if (align == 3)
11693 return false;
11694 }
11695 else if (type == 6) // when �0110�
11696 {
11697 // regs = 3; if align<1> == �1� then UNDEFINED;
11698 regs = 3;
11699 if (BitIsSet (align, 1))
11700 return false;
11701 }
11702 else if (type == 2) // when �0010�
11703 // regs = 4;
11704 regs = 4;
11705 else // otherwise
11706 // SEE �Related encodings�;
11707 return false;
11708
11709 // alignment = if align == �00� then 1 else 4 << UInt(align);
11710 if (align == 0)
11711 alignment = 1;
11712 else
11713 alignment = 4 << align;
11714
11715 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11716 ebytes = 1 << Bits32 (opcode,7, 6);
11717 esize = 8 * ebytes;
11718 elements = 8 / ebytes;
11719
11720 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11721 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11722 n = Bits32 (opcode, 19, 16);
11723 m = Bits32 (opcode, 3, 0);
11724
11725 // wback = (m != 15); register_index = (m != 15 && m != 13);
11726 wback = (m != 15);
11727 register_index = ((m != 15) && (m != 13));
11728
11729 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11730 if ((d + regs) > 32)
11731 return false;
11732
11733 if (n == 15)
11734 return false;
11735
11736 }
11737 break;
11738
11739 default:
11740 return false;
11741 }
11742
11743 RegisterInfo base_reg;
11744 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11745
11746 uint32_t Rn = ReadCoreReg (n, &success);
11747 if (!success)
11748 return false;
11749
11750 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11751 addr_t address = Rn;
11752 if ((address % alignment) != 0)
11753 return false;
11754
11755 EmulateInstruction::Context context;
11756 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11757 if (wback)
11758 {
11759 uint32_t Rm = ReadCoreReg (m, &success);
11760 if (!success)
11761 return false;
11762
11763 uint32_t offset;
11764 if (register_index)
11765 offset = Rm;
11766 else
11767 offset = 8 * regs;
11768
11769 context.type = eContextAdjustBaseRegister;
11770 context.SetRegisterPlusOffset (base_reg, offset);
11771
11772 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11773 return false;
11774 }
11775
11776 RegisterInfo data_reg;
11777 context.type = eContextRegisterStore;
11778 // for r = 0 to regs-1
11779 for (uint32_t r = 0; r < regs; ++r)
11780 {
11781 GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d + r, data_reg);
11782 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);
11783 if (!success)
11784 return false;
11785
11786 // for e = 0 to elements-1
11787 for (uint32_t e = 0; e < elements; ++e)
11788 {
11789 // MemU[address,ebytes] = Elem[D[d+r],e,esize];
11790 uint64_t word = Bits64 (register_data, ((e + 1) * esize) - 1, e * esize);
11791
11792 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11793 if (!MemUWrite (context, address, word, ebytes))
11794 return false;
11795
11796 // address = address + ebytes;
11797 address = address + ebytes;
11798 }
11799 }
11800 }
11801 return true;
11802 }
11803
11804 // A8.6.392 VST1 (single element from one lane)
11805 // This instruction stores one element to memory from one element of a register.
11806 bool
EmulateVST1Single(const uint32_t opcode,ARMEncoding encoding)11807 EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding encoding)
11808 {
11809 #if 0
11810 if ConditionPassed() then
11811 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11812 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11813 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11814 MemU[address,ebytes] = Elem[D[d],index,esize];
11815 #endif
11816
11817 bool success = false;
11818
11819 if (ConditionPassed (opcode))
11820 {
11821 uint32_t ebytes;
11822 uint32_t esize;
11823 uint32_t index;
11824 uint32_t alignment;
11825 uint32_t d;
11826 uint32_t n;
11827 uint32_t m;
11828 bool wback;
11829 bool register_index;
11830
11831 switch (encoding)
11832 {
11833 case eEncodingT1:
11834 case eEncodingA1:
11835 {
11836 uint32_t size = Bits32 (opcode, 11, 10);
11837 uint32_t index_align = Bits32 (opcode, 7, 4);
11838
11839 // if size == �11� then UNDEFINED;
11840 if (size == 3)
11841 return false;
11842
11843 // case size of
11844 if (size == 0) // when �00�
11845 {
11846 // if index_align<0> != �0� then UNDEFINED;
11847 if (BitIsClear (index_align, 0))
11848 return false;
11849 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11850 ebytes = 1;
11851 esize = 8;
11852 index = Bits32 (index_align, 3, 1);
11853 alignment = 1;
11854 }
11855 else if (size == 1) // when �01�
11856 {
11857 // if index_align<1> != �0� then UNDEFINED;
11858 if (BitIsClear (index_align, 1))
11859 return false;
11860
11861 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11862 ebytes = 2;
11863 esize = 16;
11864 index = Bits32 (index_align, 3, 2);
11865
11866 // alignment = if index_align<0> == �0� then 1 else 2;
11867 if (BitIsClear (index_align, 0))
11868 alignment = 1;
11869 else
11870 alignment = 2;
11871 }
11872 else if (size == 2) // when �10�
11873 {
11874 // if index_align<2> != �0� then UNDEFINED;
11875 if (BitIsClear (index_align, 2))
11876 return false;
11877
11878 // if index_align<1:0> != �00� && index_align<1:0> != �11� then UNDEFINED;
11879 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11880 return false;
11881
11882 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11883 ebytes = 4;
11884 esize = 32;
11885 index = Bit32 (index_align, 3);
11886
11887 // alignment = if index_align<1:0> == �00� then 1 else 4;
11888 if (Bits32 (index_align, 1, 0) == 0)
11889 alignment = 1;
11890 else
11891 alignment = 4;
11892 }
11893 else
11894 {
11895 return false;
11896 }
11897 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11898 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11899 n = Bits32 (opcode, 19, 16);
11900 m = Bits32 (opcode, 3, 0);
11901
11902 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11903 wback = (m != 15);
11904 register_index = ((m != 15) && (m != 13));
11905
11906 if (n == 15)
11907 return false;
11908 }
11909 break;
11910
11911 default:
11912 return false;
11913 }
11914
11915 RegisterInfo base_reg;
11916 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11917
11918 uint32_t Rn = ReadCoreReg (n, &success);
11919 if (!success)
11920 return false;
11921
11922 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11923 addr_t address = Rn;
11924 if ((address % alignment) != 0)
11925 return false;
11926
11927 EmulateInstruction::Context context;
11928 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11929 if (wback)
11930 {
11931 uint32_t Rm = ReadCoreReg (m, &success);
11932 if (!success)
11933 return false;
11934
11935 uint32_t offset;
11936 if (register_index)
11937 offset = Rm;
11938 else
11939 offset = ebytes;
11940
11941 context.type = eContextAdjustBaseRegister;
11942 context.SetRegisterPlusOffset (base_reg, offset);
11943
11944 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11945 return false;
11946 }
11947
11948 // MemU[address,ebytes] = Elem[D[d],index,esize];
11949 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11950 if (!success)
11951 return false;
11952
11953 uint64_t word = Bits64 (register_data, ((index + 1) * esize) - 1, index * esize);
11954
11955 RegisterInfo data_reg;
11956 GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d, data_reg);
11957 context.type = eContextRegisterStore;
11958 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11959
11960 if (!MemUWrite (context, address, word, ebytes))
11961 return false;
11962 }
11963 return true;
11964 }
11965
11966 // A8.6.309 VLD1 (single element to all lanes)
11967 // This instruction loads one element from memory into every element of one or two vectors.
11968 bool
EmulateVLD1SingleAll(const uint32_t opcode,const ARMEncoding encoding)11969 EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEncoding encoding)
11970 {
11971 #if 0
11972 if ConditionPassed() then
11973 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11974 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11975 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11976 replicated_element = Replicate(MemU[address,ebytes], elements);
11977 for r = 0 to regs-1
11978 D[d+r] = replicated_element;
11979 #endif
11980
11981 bool success = false;
11982
11983 if (ConditionPassed (opcode))
11984 {
11985 uint32_t ebytes;
11986 uint32_t elements;
11987 uint32_t regs;
11988 uint32_t alignment;
11989 uint32_t d;
11990 uint32_t n;
11991 uint32_t m;
11992 bool wback;
11993 bool register_index;
11994
11995 switch (encoding)
11996 {
11997 case eEncodingT1:
11998 case eEncodingA1:
11999 {
12000 //if size == �11� || (size == �00� && a == �1�) then UNDEFINED;
12001 uint32_t size = Bits32 (opcode, 7, 6);
12002 if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4)))
12003 return false;
12004
12005 //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == �0� then 1 else 2;
12006 ebytes = 1 << size;
12007 elements = 8 / ebytes;
12008 if (BitIsClear (opcode, 5))
12009 regs = 1;
12010 else
12011 regs = 2;
12012
12013 //alignment = if a == �0� then 1 else ebytes;
12014 if (BitIsClear (opcode, 4))
12015 alignment = 1;
12016 else
12017 alignment = ebytes;
12018
12019 //d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12020 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
12021 n = Bits32 (opcode, 19, 16);
12022 m = Bits32 (opcode, 3, 0);
12023
12024 //wback = (m != 15); register_index = (m != 15 && m != 13);
12025 wback = (m != 15);
12026 register_index = ((m != 15) && (m != 13));
12027
12028 //if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
12029 if ((d + regs) > 32)
12030 return false;
12031
12032 if (n == 15)
12033 return false;
12034 }
12035 break;
12036
12037 default:
12038 return false;
12039 }
12040
12041 RegisterInfo base_reg;
12042 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
12043
12044 uint32_t Rn = ReadCoreReg (n, &success);
12045 if (!success)
12046 return false;
12047
12048 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12049 addr_t address = Rn;
12050 if ((address % alignment) != 0)
12051 return false;
12052
12053 EmulateInstruction::Context context;
12054 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12055 if (wback)
12056 {
12057 uint32_t Rm = ReadCoreReg (m, &success);
12058 if (!success)
12059 return false;
12060
12061 uint32_t offset;
12062 if (register_index)
12063 offset = Rm;
12064 else
12065 offset = ebytes;
12066
12067 context.type = eContextAdjustBaseRegister;
12068 context.SetRegisterPlusOffset (base_reg, offset);
12069
12070 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
12071 return false;
12072 }
12073
12074 // replicated_element = Replicate(MemU[address,ebytes], elements);
12075
12076 context.type = eContextRegisterLoad;
12077 uint64_t word = MemURead (context, address, ebytes, 0, &success);
12078 if (!success)
12079 return false;
12080
12081 uint64_t replicated_element = 0;
12082 uint32_t esize = ebytes * 8;
12083 for (uint32_t e = 0; e < elements; ++e)
12084 replicated_element = (replicated_element << esize) | Bits64 (word, esize - 1, 0);
12085
12086 // for r = 0 to regs-1
12087 for (uint32_t r = 0; r < regs; ++r)
12088 {
12089 // D[d+r] = replicated_element;
12090 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, replicated_element))
12091 return false;
12092 }
12093 }
12094 return true;
12095 }
12096
12097 // B6.2.13 SUBS PC, LR and related instructions
12098 //The SUBS PC, LR, #<const? instruction provides an exception return without the use of the stack. It subtracts the
12099 // immediate constant from the LR, branches to the resulting address, and also copies the SPSR to the CPSR.
12100 bool
EmulateSUBSPcLrEtc(const uint32_t opcode,const ARMEncoding encoding)12101 EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncoding encoding)
12102 {
12103 #if 0
12104 if ConditionPassed() then
12105 EncodingSpecificOperations();
12106 if CurrentInstrSet() == InstrSet_ThumbEE then
12107 UNPREDICTABLE;
12108 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
12109 case opcode of
12110 when �0000� result = R[n] AND operand2; // AND
12111 when �0001� result = R[n] EOR operand2; // EOR
12112 when �0010� (result, -, -) = AddWithCarry(R[n], NOT(operand2), �1�); // SUB
12113 when �0011� (result, -, -) = AddWithCarry(NOT(R[n]), operand2, �1�); // RSB
12114 when �0100� (result, -, -) = AddWithCarry(R[n], operand2, �0�); // ADD
12115 when �0101� (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12116 when �0110� (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12117 when �0111� (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12118 when �1100� result = R[n] OR operand2; // ORR
12119 when �1101� result = operand2; // MOV
12120 when �1110� result = R[n] AND NOT(operand2); // BIC
12121 when �1111� result = NOT(operand2); // MVN
12122 CPSRWriteByInstr(SPSR[], �1111�, TRUE);
12123 BranchWritePC(result);
12124 #endif
12125
12126 bool success = false;
12127
12128 if (ConditionPassed (opcode))
12129 {
12130 uint32_t n;
12131 uint32_t m;
12132 uint32_t imm32;
12133 bool register_form;
12134 ARM_ShifterType shift_t;
12135 uint32_t shift_n;
12136 uint32_t code;
12137
12138 switch (encoding)
12139 {
12140 case eEncodingT1:
12141 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE
12142 // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = �0010�; // = SUB
12143 n = 14;
12144 imm32 = Bits32 (opcode, 7, 0);
12145 register_form = false;
12146 code = 2;
12147
12148 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
12149 if (InITBlock() && !LastInITBlock())
12150 return false;
12151
12152 break;
12153
12154 case eEncodingA1:
12155 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
12156 n = Bits32 (opcode, 19, 16);
12157 imm32 = ARMExpandImm (opcode);
12158 register_form = false;
12159 code = Bits32 (opcode, 24, 21);
12160
12161 break;
12162
12163 case eEncodingA2:
12164 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
12165 n = Bits32 (opcode, 19, 16);
12166 m = Bits32 (opcode, 3, 0);
12167 register_form = true;
12168
12169 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
12170 shift_n = DecodeImmShiftARM (opcode, shift_t);
12171
12172 break;
12173
12174 default:
12175 return false;
12176 }
12177
12178 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
12179 uint32_t operand2;
12180 if (register_form)
12181 {
12182 uint32_t Rm = ReadCoreReg (m, &success);
12183 if (!success)
12184 return false;
12185
12186 operand2 = Shift (Rm, shift_t, shift_n, APSR_C, &success);
12187 if (!success)
12188 return false;
12189 }
12190 else
12191 {
12192 operand2 = imm32;
12193 }
12194
12195 uint32_t Rn = ReadCoreReg (n, &success);
12196 if (!success)
12197 return false;
12198
12199 AddWithCarryResult result;
12200
12201 // case opcode of
12202 switch (code)
12203 {
12204 case 0: // when �0000�
12205 // result = R[n] AND operand2; // AND
12206 result.result = Rn & operand2;
12207 break;
12208
12209 case 1: // when �0001�
12210 // result = R[n] EOR operand2; // EOR
12211 result.result = Rn ^ operand2;
12212 break;
12213
12214 case 2: // when �0010�
12215 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), �1�); // SUB
12216 result = AddWithCarry (Rn, ~(operand2), 1);
12217 break;
12218
12219 case 3: // when �0011�
12220 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, �1�); // RSB
12221 result = AddWithCarry (~(Rn), operand2, 1);
12222 break;
12223
12224 case 4: // when �0100�
12225 // (result, -, -) = AddWithCarry(R[n], operand2, �0�); // ADD
12226 result = AddWithCarry (Rn, operand2, 0);
12227 break;
12228
12229 case 5: // when �0101�
12230 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12231 result = AddWithCarry (Rn, operand2, APSR_C);
12232 break;
12233
12234 case 6: // when �0110�
12235 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12236 result = AddWithCarry (Rn, ~(operand2), APSR_C);
12237 break;
12238
12239 case 7: // when �0111�
12240 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12241 result = AddWithCarry (~(Rn), operand2, APSR_C);
12242 break;
12243
12244 case 10: // when �1100�
12245 // result = R[n] OR operand2; // ORR
12246 result.result = Rn | operand2;
12247 break;
12248
12249 case 11: // when �1101�
12250 // result = operand2; // MOV
12251 result.result = operand2;
12252 break;
12253
12254 case 12: // when �1110�
12255 // result = R[n] AND NOT(operand2); // BIC
12256 result.result = Rn & ~(operand2);
12257 break;
12258
12259 case 15: // when �1111�
12260 // result = NOT(operand2); // MVN
12261 result.result = ~(operand2);
12262 break;
12263
12264 default:
12265 return false;
12266 }
12267 // CPSRWriteByInstr(SPSR[], �1111�, TRUE);
12268
12269 // For now, in emulation mode, we don't have access to the SPSR, so we will use the CPSR instead, and hope for
12270 // the best.
12271 uint32_t spsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success);
12272 if (!success)
12273 return false;
12274
12275 CPSRWriteByInstr (spsr, 15, true);
12276
12277 // BranchWritePC(result);
12278 EmulateInstruction::Context context;
12279 context.type = eContextAdjustPC;
12280 context.SetImmediate (result.result);
12281
12282 BranchWritePC (context, result.result);
12283 }
12284 return true;
12285 }
12286
12287 EmulateInstructionARM::ARMOpcode*
GetARMOpcodeForInstruction(const uint32_t opcode,uint32_t arm_isa)12288 EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
12289 {
12290 static ARMOpcode
12291 g_arm_opcodes[] =
12292 {
12293 //----------------------------------------------------------------------
12294 // Prologue instructions
12295 //----------------------------------------------------------------------
12296
12297 // push register(s)
12298 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12299 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
12300
12301 // set r7 to point to a stack offset
12302 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
12303 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
12304 // copy the stack pointer to ip
12305 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
12306 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
12307 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
12308
12309 // adjust the stack pointer
12310 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
12311 { 0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
12312
12313 // push one register
12314 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
12315 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
12316
12317 // vector push consecutive extension register(s)
12318 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12319 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
12320
12321 //----------------------------------------------------------------------
12322 // Epilogue instructions
12323 //----------------------------------------------------------------------
12324
12325 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12326 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
12327 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12328 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
12329
12330 //----------------------------------------------------------------------
12331 // Supervisor Call (previously Software Interrupt)
12332 //----------------------------------------------------------------------
12333 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
12334
12335 //----------------------------------------------------------------------
12336 // Branch instructions
12337 //----------------------------------------------------------------------
12338 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
12339 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
12340 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12341 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
12342 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
12343 // for example, "bx lr"
12344 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
12345 // bxj
12346 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
12347
12348 //----------------------------------------------------------------------
12349 // Data-processing instructions
12350 //----------------------------------------------------------------------
12351 // adc (immediate)
12352 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
12353 // adc (register)
12354 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12355 // add (immediate)
12356 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
12357 // add (register)
12358 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12359 // add (register-shifted register)
12360 { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
12361 // adr
12362 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12363 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
12364 // and (immediate)
12365 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
12366 // and (register)
12367 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12368 // bic (immediate)
12369 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
12370 // bic (register)
12371 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12372 // eor (immediate)
12373 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
12374 // eor (register)
12375 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12376 // orr (immediate)
12377 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
12378 // orr (register)
12379 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12380 // rsb (immediate)
12381 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
12382 // rsb (register)
12383 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12384 // rsc (immediate)
12385 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
12386 // rsc (register)
12387 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12388 // sbc (immediate)
12389 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
12390 // sbc (register)
12391 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12392 // sub (immediate, ARM)
12393 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
12394 // sub (sp minus immediate)
12395 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
12396 // sub (register)
12397 { 0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
12398 // teq (immediate)
12399 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
12400 // teq (register)
12401 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
12402 // tst (immediate)
12403 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
12404 // tst (register)
12405 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
12406
12407 // mov (immediate)
12408 { 0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
12409 { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" },
12410 // mov (register)
12411 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
12412 // mvn (immediate)
12413 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
12414 // mvn (register)
12415 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
12416 // cmn (immediate)
12417 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
12418 // cmn (register)
12419 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
12420 // cmp (immediate)
12421 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
12422 // cmp (register)
12423 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
12424 // asr (immediate)
12425 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
12426 // asr (register)
12427 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
12428 // lsl (immediate)
12429 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
12430 // lsl (register)
12431 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
12432 // lsr (immediate)
12433 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
12434 // lsr (register)
12435 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
12436 // rrx is a special case encoding of ror (immediate)
12437 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
12438 // ror (immediate)
12439 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
12440 // ror (register)
12441 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
12442 // mul
12443 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
12444
12445 // subs pc, lr and related instructions
12446 { 0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,#<const> | <Rn>,#<const>" },
12447 { 0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,<Rn>,<Rm{,<shift>}" },
12448
12449 //----------------------------------------------------------------------
12450 // Load instructions
12451 //----------------------------------------------------------------------
12452 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12453 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
12454 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12455 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
12456 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
12457 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
12458 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
12459 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
12460 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12461 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12462 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
12463 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
12464 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12465 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
12466 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12467 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12468 { 0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
12469 { 0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDRegister, "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
12470 { 0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12471 { 0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12472 { 0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12473 { 0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
12474 { 0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12475 { 0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12476 { 0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12477
12478 //----------------------------------------------------------------------
12479 // Store instructions
12480 //----------------------------------------------------------------------
12481 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12482 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
12483 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12484 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
12485 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
12486 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
12487 { 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
12488 { 0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
12489 { 0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
12490 { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
12491 { 0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDReg, "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
12492 { 0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12493 { 0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12494 { 0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
12495 { 0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
12496 { 0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12497 { 0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12498
12499 //----------------------------------------------------------------------
12500 // Other instructions
12501 //----------------------------------------------------------------------
12502 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
12503 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
12504 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
12505 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
12506 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
12507
12508 };
12509 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
12510
12511 for (size_t i=0; i<k_num_arm_opcodes; ++i)
12512 {
12513 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value &&
12514 (g_arm_opcodes[i].variants & arm_isa) != 0)
12515 return &g_arm_opcodes[i];
12516 }
12517 return NULL;
12518 }
12519
12520
12521 EmulateInstructionARM::ARMOpcode*
GetThumbOpcodeForInstruction(const uint32_t opcode,uint32_t arm_isa)12522 EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
12523 {
12524
12525 static ARMOpcode
12526 g_thumb_opcodes[] =
12527 {
12528 //----------------------------------------------------------------------
12529 // Prologue instructions
12530 //----------------------------------------------------------------------
12531
12532 // push register(s)
12533 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12534 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
12535 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
12536
12537 // set r7 to point to a stack offset
12538 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
12539 // copy the stack pointer to r7
12540 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
12541 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
12542 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
12543
12544 // PC-relative load into register (see also EmulateADDSPRm)
12545 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
12546
12547 // adjust the stack pointer
12548 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
12549 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
12550 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
12551 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
12552 { 0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
12553
12554 // vector push consecutive extension register(s)
12555 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12556 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
12557
12558 //----------------------------------------------------------------------
12559 // Epilogue instructions
12560 //----------------------------------------------------------------------
12561
12562 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
12563 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
12564 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12565 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
12566 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
12567 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12568 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
12569
12570 //----------------------------------------------------------------------
12571 // Supervisor Call (previously Software Interrupt)
12572 //----------------------------------------------------------------------
12573 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
12574
12575 //----------------------------------------------------------------------
12576 // If Then makes up to four following instructions conditional.
12577 //----------------------------------------------------------------------
12578 // The next 5 opcode _must_ come before the if then instruction
12579 { 0xffffffff, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop"},
12580 { 0xffffffff, 0x0000bf10, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop YIELD (yield hint)"},
12581 { 0xffffffff, 0x0000bf20, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop WFE (wait for event hint)"},
12582 { 0xffffffff, 0x0000bf30, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop WFI (wait for interrupt hint)"},
12583 { 0xffffffff, 0x0000bf40, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop SEV (send event hint)"},
12584 { 0xffffff00, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
12585
12586 //----------------------------------------------------------------------
12587 // Branch instructions
12588 //----------------------------------------------------------------------
12589 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
12590 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
12591 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
12592 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
12593 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"},
12594 // J1 == J2 == 1
12595 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
12596 // J1 == J2 == 1
12597 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12598 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
12599 // for example, "bx lr"
12600 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
12601 // bxj
12602 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
12603 // compare and branch
12604 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
12605 // table branch byte
12606 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
12607 // table branch halfword
12608 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
12609
12610 //----------------------------------------------------------------------
12611 // Data-processing instructions
12612 //----------------------------------------------------------------------
12613 // adc (immediate)
12614 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
12615 // adc (register)
12616 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
12617 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
12618 // add (register)
12619 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
12620 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
12621 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
12622 // adr
12623 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12624 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
12625 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12626 // and (immediate)
12627 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
12628 // and (register)
12629 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
12630 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
12631 // bic (immediate)
12632 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
12633 // bic (register)
12634 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
12635 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
12636 // eor (immediate)
12637 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
12638 // eor (register)
12639 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
12640 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
12641 // orr (immediate)
12642 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
12643 // orr (register)
12644 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
12645 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
12646 // rsb (immediate)
12647 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
12648 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
12649 // rsb (register)
12650 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
12651 // sbc (immediate)
12652 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
12653 // sbc (register)
12654 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
12655 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
12656 // add (immediate, Thumb)
12657 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
12658 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
12659 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
12660 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
12661 // sub (immediate, Thumb)
12662 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
12663 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
12664 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
12665 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
12666 // sub (sp minus immediate)
12667 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
12668 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
12669 // sub (register)
12670 { 0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
12671 { 0xffe08000, 0xeba00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"},
12672 // teq (immediate)
12673 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
12674 // teq (register)
12675 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
12676 // tst (immediate)
12677 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
12678 // tst (register)
12679 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
12680 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
12681
12682
12683 // move from high register to high register
12684 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
12685 // move from low register to low register
12686 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
12687 // mov{s}<c>.w <Rd>, <Rm>
12688 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
12689 // move immediate
12690 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
12691 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
12692 { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
12693 // mvn (immediate)
12694 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
12695 // mvn (register)
12696 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
12697 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
12698 // cmn (immediate)
12699 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
12700 // cmn (register)
12701 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
12702 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
12703 // cmp (immediate)
12704 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
12705 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
12706 // cmp (register) (Rn and Rm both from r0-r7)
12707 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
12708 // cmp (register) (Rn and Rm not both from r0-r7)
12709 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
12710 // asr (immediate)
12711 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
12712 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
12713 // asr (register)
12714 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
12715 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
12716 // lsl (immediate)
12717 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
12718 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
12719 // lsl (register)
12720 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
12721 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
12722 // lsr (immediate)
12723 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
12724 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
12725 // lsr (register)
12726 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
12727 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
12728 // rrx is a special case encoding of ror (immediate)
12729 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
12730 // ror (immediate)
12731 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
12732 // ror (register)
12733 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
12734 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
12735 // mul
12736 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
12737 // mul
12738 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
12739
12740 // subs pc, lr and related instructions
12741 { 0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>" },
12742
12743 //----------------------------------------------------------------------
12744 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE LDM.. Instructions in this table;
12745 // otherwise the wrong instructions will be selected.
12746 //----------------------------------------------------------------------
12747
12748 { 0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
12749 { 0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" },
12750
12751 //----------------------------------------------------------------------
12752 // Load instructions
12753 //----------------------------------------------------------------------
12754 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12755 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
12756 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12757 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
12758 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
12759 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
12760 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
12761 // Thumb2 PC-relative load into register
12762 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
12763 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
12764 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
12765 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
12766 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
12767 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}" },
12768 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
12769 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
12770 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12771 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
12772 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
12773 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
12774 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12775 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
12776 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12777 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
12778 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12779 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
12780 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
12781 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12782 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
12783 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12784 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12785 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
12786 { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12787 { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
12788 { 0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12789 { 0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>" },
12790 { 0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12791 { 0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
12792 { 0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
12793 { 0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
12794 { 0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12795
12796 //----------------------------------------------------------------------
12797 // Store instructions
12798 //----------------------------------------------------------------------
12799 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12800 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
12801 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12802 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
12803 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
12804 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
12805 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
12806 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
12807 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
12808 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
12809 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
12810 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
12811 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
12812 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12813 { 0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]" },
12814 { 0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
12815 { 0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12816 { 0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12817 { 0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12818 { 0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
12819 { 0xffb00000, 0xf9000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12820 { 0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12821
12822 //----------------------------------------------------------------------
12823 // Other instructions
12824 //----------------------------------------------------------------------
12825 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
12826 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12827 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
12828 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
12829 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
12830 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12831 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
12832 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
12833 };
12834
12835 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
12836 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
12837 {
12838 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value &&
12839 (g_thumb_opcodes[i].variants & arm_isa) != 0)
12840 return &g_thumb_opcodes[i];
12841 }
12842 return NULL;
12843 }
12844
12845 bool
SetArchitecture(const ArchSpec & arch)12846 EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
12847 {
12848 m_arch = arch;
12849 m_arm_isa = 0;
12850 const char *arch_cstr = arch.GetArchitectureName ();
12851 if (arch_cstr)
12852 {
12853 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
12854 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
12855 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
12856 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
12857 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
12858 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
12859 else if (0 == ::strcasecmp(arch_cstr, "armv7s")) m_arm_isa = ARMv7S;
12860 else if (0 == ::strcasecmp(arch_cstr, "arm")) m_arm_isa = ARMvAll;
12861 else if (0 == ::strcasecmp(arch_cstr, "thumb")) m_arm_isa = ARMvAll;
12862 else if (0 == ::strncasecmp(arch_cstr,"armv4", 5)) m_arm_isa = ARMv4;
12863 else if (0 == ::strncasecmp(arch_cstr,"armv6", 5)) m_arm_isa = ARMv6;
12864 else if (0 == ::strncasecmp(arch_cstr,"armv7", 5)) m_arm_isa = ARMv7;
12865 else if (0 == ::strncasecmp(arch_cstr,"armv8", 5)) m_arm_isa = ARMv8;
12866 }
12867 return m_arm_isa != 0;
12868 }
12869
12870 bool
SetInstruction(const Opcode & insn_opcode,const Address & inst_addr,Target * target)12871 EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target)
12872 {
12873 if (EmulateInstruction::SetInstruction (insn_opcode, inst_addr, target))
12874 {
12875 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb)
12876 m_opcode_mode = eModeThumb;
12877 else
12878 {
12879 AddressClass addr_class = inst_addr.GetAddressClass();
12880
12881 if ((addr_class == eAddressClassCode) || (addr_class == eAddressClassUnknown))
12882 m_opcode_mode = eModeARM;
12883 else if (addr_class == eAddressClassCodeAlternateISA)
12884 m_opcode_mode = eModeThumb;
12885 else
12886 return false;
12887 }
12888 if (m_opcode_mode == eModeThumb)
12889 m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T;
12890 else
12891 m_opcode_cpsr = CPSR_MODE_USR;
12892 return true;
12893 }
12894 return false;
12895 }
12896
12897 bool
ReadInstruction()12898 EmulateInstructionARM::ReadInstruction ()
12899 {
12900 bool success = false;
12901 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
12902 if (success)
12903 {
12904 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
12905 if (success)
12906 {
12907 Context read_inst_context;
12908 read_inst_context.type = eContextReadOpcode;
12909 read_inst_context.SetNoArgs ();
12910
12911 if (m_opcode_cpsr & MASK_CPSR_T)
12912 {
12913 m_opcode_mode = eModeThumb;
12914 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
12915
12916 if (success)
12917 {
12918 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
12919 {
12920 m_opcode.SetOpcode16 (thumb_opcode, GetByteOrder());
12921 }
12922 else
12923 {
12924 m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success), GetByteOrder());
12925 }
12926 }
12927 }
12928 else
12929 {
12930 m_opcode_mode = eModeARM;
12931 m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success), GetByteOrder());
12932 }
12933 }
12934 }
12935 if (!success)
12936 {
12937 m_opcode_mode = eModeInvalid;
12938 m_addr = LLDB_INVALID_ADDRESS;
12939 }
12940 return success;
12941 }
12942
12943 uint32_t
ArchVersion()12944 EmulateInstructionARM::ArchVersion ()
12945 {
12946 return m_arm_isa;
12947 }
12948
12949 bool
ConditionPassed(const uint32_t opcode,bool * is_conditional)12950 EmulateInstructionARM::ConditionPassed (const uint32_t opcode, bool *is_conditional)
12951 {
12952 // If we are ignoring conditions, then always return true.
12953 // this allows us to iterate over disassembly code and still
12954 // emulate an instruction even if we don't have all the right
12955 // bits set in the CPSR register...
12956 if (m_ignore_conditions)
12957 return true;
12958
12959 if (is_conditional)
12960 *is_conditional = true;
12961
12962 const uint32_t cond = CurrentCond (opcode);
12963
12964 if (cond == UINT32_MAX)
12965 return false;
12966
12967 bool result = false;
12968 switch (UnsignedBits(cond, 3, 1))
12969 {
12970 case 0:
12971 if (m_opcode_cpsr == 0)
12972 result = true;
12973 else
12974 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;
12975 break;
12976 case 1:
12977 if (m_opcode_cpsr == 0)
12978 result = true;
12979 else
12980 result = (m_opcode_cpsr & MASK_CPSR_C) != 0;
12981 break;
12982 case 2:
12983 if (m_opcode_cpsr == 0)
12984 result = true;
12985 else
12986 result = (m_opcode_cpsr & MASK_CPSR_N) != 0;
12987 break;
12988 case 3:
12989 if (m_opcode_cpsr == 0)
12990 result = true;
12991 else
12992 result = (m_opcode_cpsr & MASK_CPSR_V) != 0;
12993 break;
12994 case 4:
12995 if (m_opcode_cpsr == 0)
12996 result = true;
12997 else
12998 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
12999 break;
13000 case 5:
13001 if (m_opcode_cpsr == 0)
13002 result = true;
13003 else
13004 {
13005 bool n = (m_opcode_cpsr & MASK_CPSR_N);
13006 bool v = (m_opcode_cpsr & MASK_CPSR_V);
13007 result = n == v;
13008 }
13009 break;
13010 case 6:
13011 if (m_opcode_cpsr == 0)
13012 result = true;
13013 else
13014 {
13015 bool n = (m_opcode_cpsr & MASK_CPSR_N);
13016 bool v = (m_opcode_cpsr & MASK_CPSR_V);
13017 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
13018 }
13019 break;
13020 case 7:
13021 // Always execute (cond == 0b1110, or the special 0b1111 which gives
13022 // opcodes different meanings, but always means execution happpens.
13023 if (is_conditional)
13024 *is_conditional = false;
13025 result = true;
13026 break;
13027 }
13028
13029 if (cond & 1)
13030 result = !result;
13031 return result;
13032 }
13033
13034 uint32_t
CurrentCond(const uint32_t opcode)13035 EmulateInstructionARM::CurrentCond (const uint32_t opcode)
13036 {
13037 switch (m_opcode_mode)
13038 {
13039 case eModeInvalid:
13040 break;
13041
13042 case eModeARM:
13043 return UnsignedBits(opcode, 31, 28);
13044
13045 case eModeThumb:
13046 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
13047 // 'cond' field of the encoding.
13048 {
13049 const uint32_t byte_size = m_opcode.GetByteSize();
13050 if (byte_size == 2)
13051 {
13052 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f)
13053 return Bits32(opcode, 11, 7);
13054 }
13055 else if (byte_size == 4)
13056 {
13057 if (Bits32(opcode, 31, 27) == 0x1e &&
13058 Bits32(opcode, 15, 14) == 0x02 &&
13059 Bits32(opcode, 12, 12) == 0x00 &&
13060 Bits32(opcode, 25, 22) <= 0x0d)
13061 {
13062 return Bits32(opcode, 25, 22);
13063 }
13064 }
13065 else
13066 // We have an invalid thumb instruction, let's bail out.
13067 break;
13068
13069 return m_it_session.GetCond();
13070 }
13071 }
13072 return UINT32_MAX; // Return invalid value
13073 }
13074
13075 bool
InITBlock()13076 EmulateInstructionARM::InITBlock()
13077 {
13078 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
13079 }
13080
13081 bool
LastInITBlock()13082 EmulateInstructionARM::LastInITBlock()
13083 {
13084 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
13085 }
13086
13087 bool
BadMode(uint32_t mode)13088 EmulateInstructionARM::BadMode (uint32_t mode)
13089 {
13090
13091 switch (mode)
13092 {
13093 case 16: return false; // '10000'
13094 case 17: return false; // '10001'
13095 case 18: return false; // '10010'
13096 case 19: return false; // '10011'
13097 case 22: return false; // '10110'
13098 case 23: return false; // '10111'
13099 case 27: return false; // '11011'
13100 case 31: return false; // '11111'
13101 default: return true;
13102 }
13103 return true;
13104 }
13105
13106 bool
CurrentModeIsPrivileged()13107 EmulateInstructionARM::CurrentModeIsPrivileged ()
13108 {
13109 uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0);
13110
13111 if (BadMode (mode))
13112 return false;
13113
13114 if (mode == 16)
13115 return false;
13116
13117 return true;
13118 }
13119
13120 void
CPSRWriteByInstr(uint32_t value,uint32_t bytemask,bool affect_execstate)13121 EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
13122 {
13123 bool privileged = CurrentModeIsPrivileged();
13124
13125 uint32_t tmp_cpsr = Bits32 (m_opcode_cpsr, 23, 20) << 20;
13126
13127 if (BitIsSet (bytemask, 3))
13128 {
13129 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
13130 if (affect_execstate)
13131 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
13132 }
13133
13134 if (BitIsSet (bytemask, 2))
13135 {
13136 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
13137 }
13138
13139 if (BitIsSet (bytemask, 1))
13140 {
13141 if (affect_execstate)
13142 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
13143 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
13144 if (privileged)
13145 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
13146 }
13147
13148 if (BitIsSet (bytemask, 0))
13149 {
13150 if (privileged)
13151 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
13152 if (affect_execstate)
13153 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
13154 if (privileged)
13155 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
13156 }
13157
13158 m_opcode_cpsr = tmp_cpsr;
13159 }
13160
13161
13162 bool
BranchWritePC(const Context & context,uint32_t addr)13163 EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
13164 {
13165 addr_t target;
13166
13167 // Check the current instruction set.
13168 if (CurrentInstrSet() == eModeARM)
13169 target = addr & 0xfffffffc;
13170 else
13171 target = addr & 0xfffffffe;
13172
13173 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
13174 return false;
13175
13176 return true;
13177 }
13178
13179 // As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
13180 bool
BXWritePC(Context & context,uint32_t addr)13181 EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
13182 {
13183 addr_t target;
13184 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
13185 // we want to record it and issue a WriteRegister callback so the clients
13186 // can track the mode changes accordingly.
13187 bool cpsr_changed = false;
13188
13189 if (BitIsSet(addr, 0))
13190 {
13191 if (CurrentInstrSet() != eModeThumb)
13192 {
13193 SelectInstrSet(eModeThumb);
13194 cpsr_changed = true;
13195 }
13196 target = addr & 0xfffffffe;
13197 context.SetISA (eModeThumb);
13198 }
13199 else if (BitIsClear(addr, 1))
13200 {
13201 if (CurrentInstrSet() != eModeARM)
13202 {
13203 SelectInstrSet(eModeARM);
13204 cpsr_changed = true;
13205 }
13206 target = addr & 0xfffffffc;
13207 context.SetISA (eModeARM);
13208 }
13209 else
13210 return false; // address<1:0> == '10' => UNPREDICTABLE
13211
13212 if (cpsr_changed)
13213 {
13214 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
13215 return false;
13216 }
13217 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
13218 return false;
13219
13220 return true;
13221 }
13222
13223 // Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
13224 bool
LoadWritePC(Context & context,uint32_t addr)13225 EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
13226 {
13227 if (ArchVersion() >= ARMv5T)
13228 return BXWritePC(context, addr);
13229 else
13230 return BranchWritePC((const Context)context, addr);
13231 }
13232
13233 // Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
13234 bool
ALUWritePC(Context & context,uint32_t addr)13235 EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
13236 {
13237 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
13238 return BXWritePC(context, addr);
13239 else
13240 return BranchWritePC((const Context)context, addr);
13241 }
13242
13243 EmulateInstructionARM::Mode
CurrentInstrSet()13244 EmulateInstructionARM::CurrentInstrSet ()
13245 {
13246 return m_opcode_mode;
13247 }
13248
13249 // Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
13250 // ReadInstruction() is performed. This function has a side effect of updating
13251 // the m_new_inst_cpsr member variable if necessary.
13252 bool
SelectInstrSet(Mode arm_or_thumb)13253 EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
13254 {
13255 m_new_inst_cpsr = m_opcode_cpsr;
13256 switch (arm_or_thumb)
13257 {
13258 default:
13259 return false;
13260 case eModeARM:
13261 // Clear the T bit.
13262 m_new_inst_cpsr &= ~MASK_CPSR_T;
13263 break;
13264 case eModeThumb:
13265 // Set the T bit.
13266 m_new_inst_cpsr |= MASK_CPSR_T;
13267 break;
13268 }
13269 return true;
13270 }
13271
13272 // This function returns TRUE if the processor currently provides support for
13273 // unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
13274 // controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
13275 bool
UnalignedSupport()13276 EmulateInstructionARM::UnalignedSupport()
13277 {
13278 return (ArchVersion() >= ARMv7);
13279 }
13280
13281 // The main addition and subtraction instructions can produce status information
13282 // about both unsigned carry and signed overflow conditions. This status
13283 // information can be used to synthesize multi-word additions and subtractions.
13284 EmulateInstructionARM::AddWithCarryResult
AddWithCarry(uint32_t x,uint32_t y,uint8_t carry_in)13285 EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
13286 {
13287 uint32_t result;
13288 uint8_t carry_out;
13289 uint8_t overflow;
13290
13291 uint64_t unsigned_sum = x + y + carry_in;
13292 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
13293
13294 result = UnsignedBits(unsigned_sum, 31, 0);
13295 // carry_out = (result == unsigned_sum ? 0 : 1);
13296 overflow = ((int32_t)result == signed_sum ? 0 : 1);
13297
13298 if (carry_in)
13299 carry_out = ((int32_t) x >= (int32_t) (~y)) ? 1 : 0;
13300 else
13301 carry_out = ((int32_t) x > (int32_t) y) ? 1 : 0;
13302
13303 AddWithCarryResult res = { result, carry_out, overflow };
13304 return res;
13305 }
13306
13307 uint32_t
ReadCoreReg(uint32_t num,bool * success)13308 EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
13309 {
13310 uint32_t reg_kind, reg_num;
13311 switch (num)
13312 {
13313 case SP_REG:
13314 reg_kind = eRegisterKindGeneric;
13315 reg_num = LLDB_REGNUM_GENERIC_SP;
13316 break;
13317 case LR_REG:
13318 reg_kind = eRegisterKindGeneric;
13319 reg_num = LLDB_REGNUM_GENERIC_RA;
13320 break;
13321 case PC_REG:
13322 reg_kind = eRegisterKindGeneric;
13323 reg_num = LLDB_REGNUM_GENERIC_PC;
13324 break;
13325 default:
13326 if (num < SP_REG)
13327 {
13328 reg_kind = eRegisterKindDWARF;
13329 reg_num = dwarf_r0 + num;
13330 }
13331 else
13332 {
13333 //assert(0 && "Invalid register number");
13334 *success = false;
13335 return UINT32_MAX;
13336 }
13337 break;
13338 }
13339
13340 // Read our register.
13341 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
13342
13343 // When executing an ARM instruction , PC reads as the address of the current
13344 // instruction plus 8.
13345 // When executing a Thumb instruction , PC reads as the address of the current
13346 // instruction plus 4.
13347 if (num == 15)
13348 {
13349 if (CurrentInstrSet() == eModeARM)
13350 val += 8;
13351 else
13352 val += 4;
13353 }
13354
13355 return val;
13356 }
13357
13358 // Write the result to the ARM core register Rd, and optionally update the
13359 // condition flags based on the result.
13360 //
13361 // This helper method tries to encapsulate the following pseudocode from the
13362 // ARM Architecture Reference Manual:
13363 //
13364 // if d == 15 then // Can only occur for encoding A1
13365 // ALUWritePC(result); // setflags is always FALSE here
13366 // else
13367 // R[d] = result;
13368 // if setflags then
13369 // APSR.N = result<31>;
13370 // APSR.Z = IsZeroBit(result);
13371 // APSR.C = carry;
13372 // // APSR.V unchanged
13373 //
13374 // In the above case, the API client does not pass in the overflow arg, which
13375 // defaults to ~0u.
13376 bool
WriteCoreRegOptionalFlags(Context & context,const uint32_t result,const uint32_t Rd,bool setflags,const uint32_t carry,const uint32_t overflow)13377 EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
13378 const uint32_t result,
13379 const uint32_t Rd,
13380 bool setflags,
13381 const uint32_t carry,
13382 const uint32_t overflow)
13383 {
13384 if (Rd == 15)
13385 {
13386 if (!ALUWritePC (context, result))
13387 return false;
13388 }
13389 else
13390 {
13391 uint32_t reg_kind, reg_num;
13392 switch (Rd)
13393 {
13394 case SP_REG:
13395 reg_kind = eRegisterKindGeneric;
13396 reg_num = LLDB_REGNUM_GENERIC_SP;
13397 break;
13398 case LR_REG:
13399 reg_kind = eRegisterKindGeneric;
13400 reg_num = LLDB_REGNUM_GENERIC_RA;
13401 break;
13402 default:
13403 reg_kind = eRegisterKindDWARF;
13404 reg_num = dwarf_r0 + Rd;
13405 }
13406 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
13407 return false;
13408 if (setflags)
13409 return WriteFlags (context, result, carry, overflow);
13410 }
13411 return true;
13412 }
13413
13414 // This helper method tries to encapsulate the following pseudocode from the
13415 // ARM Architecture Reference Manual:
13416 //
13417 // APSR.N = result<31>;
13418 // APSR.Z = IsZeroBit(result);
13419 // APSR.C = carry;
13420 // APSR.V = overflow
13421 //
13422 // Default arguments can be specified for carry and overflow parameters, which means
13423 // not to update the respective flags.
13424 bool
WriteFlags(Context & context,const uint32_t result,const uint32_t carry,const uint32_t overflow)13425 EmulateInstructionARM::WriteFlags (Context &context,
13426 const uint32_t result,
13427 const uint32_t carry,
13428 const uint32_t overflow)
13429 {
13430 m_new_inst_cpsr = m_opcode_cpsr;
13431 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
13432 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
13433 if (carry != ~0u)
13434 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
13435 if (overflow != ~0u)
13436 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
13437 if (m_new_inst_cpsr != m_opcode_cpsr)
13438 {
13439 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
13440 return false;
13441 }
13442 return true;
13443 }
13444
13445 bool
EvaluateInstruction(uint32_t evaluate_options)13446 EmulateInstructionARM::EvaluateInstruction (uint32_t evaluate_options)
13447 {
13448 // Advance the ITSTATE bits to their values for the next instruction.
13449 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock())
13450 m_it_session.ITAdvance();
13451
13452 ARMOpcode *opcode_data = NULL;
13453
13454 if (m_opcode_mode == eModeThumb)
13455 opcode_data = GetThumbOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
13456 else if (m_opcode_mode == eModeARM)
13457 opcode_data = GetARMOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
13458
13459 if (opcode_data == NULL)
13460 return false;
13461
13462 const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
13463 m_ignore_conditions = evaluate_options & eEmulateInstructionOptionIgnoreConditions;
13464
13465 bool success = false;
13466 if (m_opcode_cpsr == 0 || m_ignore_conditions == false)
13467 {
13468 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindDWARF,
13469 dwarf_cpsr,
13470 0,
13471 &success);
13472 }
13473
13474 // Only return false if we are unable to read the CPSR if we care about conditions
13475 if (success == false && m_ignore_conditions == false)
13476 return false;
13477
13478 uint32_t orig_pc_value = 0;
13479 if (auto_advance_pc)
13480 {
13481 orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13482 if (!success)
13483 return false;
13484 }
13485
13486 // Call the Emulate... function.
13487 success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding);
13488 if (!success)
13489 return false;
13490
13491 if (auto_advance_pc)
13492 {
13493 uint32_t after_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13494 if (!success)
13495 return false;
13496
13497 if (auto_advance_pc && (after_pc_value == orig_pc_value))
13498 {
13499 if (opcode_data->size == eSize32)
13500 after_pc_value += 4;
13501 else if (opcode_data->size == eSize16)
13502 after_pc_value += 2;
13503
13504 EmulateInstruction::Context context;
13505 context.type = eContextAdvancePC;
13506 context.SetNoArgs();
13507 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc, after_pc_value))
13508 return false;
13509
13510 }
13511 }
13512 return true;
13513 }
13514
13515 bool
TestEmulation(Stream * out_stream,ArchSpec & arch,OptionValueDictionary * test_data)13516 EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data)
13517 {
13518 if (!test_data)
13519 {
13520 out_stream->Printf ("TestEmulation: Missing test data.\n");
13521 return false;
13522 }
13523
13524 static ConstString opcode_key ("opcode");
13525 static ConstString before_key ("before_state");
13526 static ConstString after_key ("after_state");
13527
13528 OptionValueSP value_sp = test_data->GetValueForKey (opcode_key);
13529
13530 uint32_t test_opcode;
13531 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeUInt64))
13532 {
13533 out_stream->Printf ("TestEmulation: Error reading opcode from test file.\n");
13534 return false;
13535 }
13536 test_opcode = value_sp->GetUInt64Value ();
13537
13538 if (arch.GetTriple().getArch() == llvm::Triple::arm)
13539 {
13540 m_opcode_mode = eModeARM;
13541 m_opcode.SetOpcode32 (test_opcode, GetByteOrder());
13542 }
13543 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
13544 {
13545 m_opcode_mode = eModeThumb;
13546 if (test_opcode < 0x10000)
13547 m_opcode.SetOpcode16 (test_opcode, GetByteOrder());
13548 else
13549 m_opcode.SetOpcode32 (test_opcode, GetByteOrder());
13550
13551 }
13552 else
13553 {
13554 out_stream->Printf ("TestEmulation: Invalid arch.\n");
13555 return false;
13556 }
13557
13558 EmulationStateARM before_state;
13559 EmulationStateARM after_state;
13560
13561 value_sp = test_data->GetValueForKey (before_key);
13562 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
13563 {
13564 out_stream->Printf ("TestEmulation: Failed to find 'before' state.\n");
13565 return false;
13566 }
13567
13568 OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary ();
13569 if (!before_state.LoadStateFromDictionary (state_dictionary))
13570 {
13571 out_stream->Printf ("TestEmulation: Failed loading 'before' state.\n");
13572 return false;
13573 }
13574
13575 value_sp = test_data->GetValueForKey (after_key);
13576 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
13577 {
13578 out_stream->Printf ("TestEmulation: Failed to find 'after' state.\n");
13579 return false;
13580 }
13581
13582 state_dictionary = value_sp->GetAsDictionary ();
13583 if (!after_state.LoadStateFromDictionary (state_dictionary))
13584 {
13585 out_stream->Printf ("TestEmulation: Failed loading 'after' state.\n");
13586 return false;
13587 }
13588
13589 SetBaton ((void *) &before_state);
13590 SetCallbacks (&EmulationStateARM::ReadPseudoMemory,
13591 &EmulationStateARM::WritePseudoMemory,
13592 &EmulationStateARM::ReadPseudoRegister,
13593 &EmulationStateARM::WritePseudoRegister);
13594
13595 bool success = EvaluateInstruction (eEmulateInstructionOptionAutoAdvancePC);
13596 if (!success)
13597 {
13598 out_stream->Printf ("TestEmulation: EvaluateInstruction() failed.\n");
13599 return false;
13600 }
13601
13602 success = before_state.CompareState (after_state);
13603 if (!success)
13604 out_stream->Printf ("TestEmulation: 'before' and 'after' states do not match.\n");
13605
13606 return success;
13607 }
13608 //
13609 //
13610 //const char *
13611 //EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)
13612 //{
13613 // if (reg_kind == eRegisterKindGeneric)
13614 // {
13615 // switch (reg_num)
13616 // {
13617 // case LLDB_REGNUM_GENERIC_PC: return "pc";
13618 // case LLDB_REGNUM_GENERIC_SP: return "sp";
13619 // case LLDB_REGNUM_GENERIC_FP: return "fp";
13620 // case LLDB_REGNUM_GENERIC_RA: return "lr";
13621 // case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";
13622 // default: return NULL;
13623 // }
13624 // }
13625 // else if (reg_kind == eRegisterKindDWARF)
13626 // {
13627 // return GetARMDWARFRegisterName (reg_num);
13628 // }
13629 // return NULL;
13630 //}
13631 //
13632 bool
CreateFunctionEntryUnwind(UnwindPlan & unwind_plan)13633 EmulateInstructionARM::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
13634 {
13635 unwind_plan.Clear();
13636 unwind_plan.SetRegisterKind (eRegisterKindDWARF);
13637
13638 UnwindPlan::RowSP row(new UnwindPlan::Row);
13639
13640 // Our previous Call Frame Address is the stack pointer
13641 row->SetCFARegister (dwarf_sp);
13642
13643 // Our previous PC is in the LR
13644 row->SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, true);
13645 unwind_plan.AppendRow (row);
13646
13647 // All other registers are the same.
13648
13649 unwind_plan.SetSourceName ("EmulateInstructionARM");
13650 unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
13651 unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes);
13652 return true;
13653 }
13654